withmock

command module
v0.0.0-...-b0df8b0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 4, 2018 License: BSD-3-Clause Imports: 7 Imported by: 0

README

withmock / mocktest

What is this?

A pair of tools to automatically mock packages for testing with gomock

How do I install it?

As you might expect:

go get github.com/qur/withmock
go get github.com/qur/withmock/mocktest

You will also need to install goimports (golang.org/x/tools/cmd/goimports), and gomock (github.com/golang/mock/gomock).

How do I use it?

withmock allows an arbitrary command to be run, but will only setup the test environment for the package in the current directory. mocktest builds it's own command to be run, but can test multiple packages at the same time.

To configure which packages get mocked, you just add "// mock" to the end of your import in the test code. Then you can use with withmock or mocktest to actually run the test. To use withmock you simply prepend withmock to your normal test command, e.g.:

withmock go test

To use mocktest you specify the packages on the command line, so to test the current directory in the same manner as the above withmock command you can just run:

mocktest

However, if you wanted to run a heirarchy of test you could run:

mocktest ./...

For more info see the documentation: http://godoc.org/github.com/qur/withmock

You can also check out the example.

Documentation

Overview

withmock is a tool to assist in mocking code for testing.

The basic idea is that you can mark import statements to indicate packages that should be mocked. Then, if you run your test via withmock then mock versions of the marked packages will be generated - and the tests will be run using those packages instead of the real ones.

Creating Mocks

To mark an import for mocking, simply append a comment consisting of just the word mock to the end of the import line in the xxx_test.go file.

So if we had the import statement:

import (
	"fmt"
	"os"
	"os/exec"

	"example.com/some/external/package"
)

then we could mark the external package for mocking by changing it to:

import (
	"fmt"
	"os"
	"os/exec"

	"example.com/some/external/package" // mock
)

The mocking is not restricted to external packages. Though often we want to keep access to the original package for use in the test code itself. So, keeping the same example, we might want to use a mock version of fmt in the code under test. So, now we change the import to:

import (
	"fmt"
	"os"
	"os/exec"

	mockfmt "fmt" // mock

	"example.com/some/external/package" // mock
)

So, when run, the non-test code will be using the mocked fmt and external packages, and the test code will have the proper fmt, the mocked fmt as mockfmt, and the mocked external package using it's own name (which will assume it ext, for the purposes of this documentation).

Using Mocks

The generated mock code behaves much like the code generated by gomock's mockgen , particularly when dealing with methods on types. Though there are some differences, due to the whole package nature.

The first thing to do with a mocked package is to set the controller. This needs to be done before any mocked method or function is called or expectation is set - otherwise the generated code will cause a panic. To set the controller, we use the special mock object returned by the MOCK() function, and call it's SetController method:

// Create a gomock controller, and arrange for it's finish to be called
ctrl := gomock.NewController(t)
defer ctrl.Finish()

// Setup the mockfmt mock package
mockfmt.MOCK().SetController(ctrl)

// Setup the ext mock package
ext.MOCK().SetController(ctrl)

Once you have set the controller then you can set your mock expectations, either using the EXPECT() function for function expectations, or the EXPECT() method for any method expectations. For example, if there was a type called UsefulType, and we were expecting it's HandyMethod to be called - followed by a message printed indicating the result, we might set our expectations as follows:

// Create a UsefulType instance
ut := &ext.UsefulType{}

// We expect to see HandyMethod called, and we want to return true
ut.EXPECT().HandyMethod().Return(true)

// And we expect to see our returned value printed
mockfmt.EXPECT().Printf("HandyMethod returned: %v\n", true)

And then finally we can call our code under test, passing it our mocked UsefulType instance:

// And now, call the code under test
importantFunction(ut)

Running the tests

And now we just need to wrap our call to "go test", so we run:

withmock go test

and gomock and the Go testing framework will do the rest for us ... :D

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL