Leveraging gomock to write a unit test for our application

Now that we are aware of the implementation details of our example project, we can go ahead and write a simple, mock-based unit test for it. Before we begin, we need to create a mock for the API interface. This can be achieved by invoking the mockgen tool with the following options:

$ mockgen \
    -destination mock/dependency.go \
    github.com/PacktPublishing/Hands-On-Software-Engineering-with-Golang/Chapter04/dependency \
    API

The preceding command does the following:

To save you the trouble of having to manually type in the preceding command, the Makefile in the Chapter04/dependency folder includes a predefined target for rebuilding the mocks that were used in this example. All you need to do is switch to the folder with the example code in it and run make mocks.

So far, so good. How can we use the mock in our tests though? The first thing we need to do is create a gomock controller and associate it with the testing.T instance that gets passed to our test function by the Go standard library. The controller instance defines a Finish method that our code must always run before returning from the test (for example, via a defer statement). This method checks the expectations that were registered on each mock object and automatically fails the test if they were not met. Here's what the preamble of our test function would look like:

The purpose of this particular unit test is to verify that a call to the AllDependencies method with a specific input yields an expected list of dependency IDs. As we saw in the previous section, the implementation of the AllDependencies method uses an externally-provided API instance to retrieve information about each dependency. Given that our test will inject a mocked API instance into the Collector dependency, our test code must declare the expected set of calls to the mock. Consider the following block of code:

Under normal circumstances, gomock would just check that the method call expectations are met, regardless of the order that they were invoked in. However, if a test relies on a sequence of method calls being performed in a particular order, it can specify this to gomock by invoking the gomock.InOrder helper function with an ordered list of expectations as arguments. This particular pattern can be seen in the preceding code snippet.

With the mock expectations in place, we can complete our unit by introducing the necessary logic to wire everything together, invoke the AllDependencies method with the input (proj0) that our mock expects, and validate that the returned output matches a predefined value ("proj1", "res1", "res2"):

This concludes our short example about using gomock to accelerate the authoring of mock-based tests. As a fun learning activity, you can experiment with changing the expected output for the preceding test so that the test fails. Then, you can work backward and try to figure out how to tweak the mock expectations to make the test pass again.