Skip to content

Experiments with James Shore's Testing Without Mock Pattern Language

License

Notifications You must be signed in to change notification settings

Suigi/nullables-sandbox

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

My Nullables Sandbox

This is a collection of experiments playing with Nullable Infrastructure Wrappers and other parts of James Shore's Testing Without Mocks Pattern Language.

High-Level Infrastructure Wrappers

DailyQuoteClient is an instance of a high-level infrastructure wrapper. It uses a low-level wrapper (JsonHttpClient) to talk to an imaginary Daily Quote Web Service.

In order to use the DailyQuoteClient in a test, it can be instantiated using the DailyQuoteClient.createNull() static factory methods.

There is a version of it that does not take any arguments, in case you need a dummy version of the client, that does not interfere with the rest of your test:

@Test
void returnsDefaultQuoteIfNoQuoteIsConfigured() {
    DailyQuoteClient quoteClient = DailyQuoteClient.createNull();

    String quote = quoteClient.fetchQuote();

    assertThat(quote)
            .isEqualTo("""
                       Default Quote
                       - Unknown""");
}

I interpret this as a variation of James' Parameterless Instantiation.

The other version of createNull takes a configuration Function as a parameter. I like setting up the client in a test using a lambda, like this:

@Test
void returnsConfiguredQuote() {
    DailyQuoteClient quoteClient = DailyQuoteClient.createNull(c -> c
            .quote("Make many more much smaller steps.", "GeePaw Hill"));

    String quote = quoteClient.fetchQuote();

    assertThat(quote)
            .isEqualTo("""
                       Make many more much smaller steps.
                       - GeePaw Hill""");
}

In my (limited) experience it can take quite some effort to build a low-level Infrastructure Wrapper. Java needs some convincing sometimes for setting up an Embedded Stub. I suppose that's true for any statically typed language. Side note: I didn't actually implement a working HTTP infrastructure wrapper in this project. The JsonHttpClient can only serve configured responses.

However, once the low-level wrapper is done, it's very straight-forward to build higher-level wrappers on top of it. The high-level createNull is implemented in the high-level terms of the application (e.g. configuring a quote). Internally, it transforms the high-level response to a low-level one (e.g. returning an HTTP response for a specific URL):

public class DailyQuoteClient {
    
    // ...
    
    public static class Config {
        
        // ...
        
        private JsonHttpClient toHttpClient() {
            if (throwTimeout) {
                return JsonHttpClient.createNull(c -> c
                    .timeout());
            }
            return JsonHttpClient.createNull(c -> c
                    .responseForUrl(
                            "https://example.com/quote",
                            new QuoteResponse(
                                    configuredQuote,
                                    configuredAuthor))
            );
        }
    }
}

About

Experiments with James Shore's Testing Without Mock Pattern Language

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages