I have the following method to test, which uses a function imported from a package.
import x.y.z
func abc() {
...
v := z.SomeFunc()
...
}
Is it possible to mock SomeFunc()
in golang?
Yes, with a simple refactoring. Create a zSomeFunc
variable of function type, initialized with z.SomeFunc
, and have your package call that instead of z.SomeFunc()
:
var zSomeFunc = z.SomeFunc
func abc() {
// ...
v := zSomeFunc()
// ...
}
In tests you may assign another function to zSomeFunc
, one that is defined in tests, and does whatever the test wants it to.
For example:
func TestAbc(t *testing.T) {
// Save current function and restore at the end:
old := zSomeFunc
defer func() { zSomeFunc = old }()
zSomeFunc = func() int {
// This will be called, do whatever you want to,
// return whatever you want to
return 1
}
// Call the tested function
abc()
// Check expected behavior
}
See related / possible duplicate: Testing os.Exit scenarios in Go with coverage information (coveralls.io/Goveralls)
One thing you can do is this:
import x.y.z
var someFunc = z.SomeFunc
func abc() {
...
v := someFunc
...
}
And in your test file you would do this.
func Test_abc() {
someFunc = mockFunc
abc()
}
But make sure that you do this in a concurrent manner, if you have multiple TestXxx
functions calling abc
or setting someFunc
you may be better of using a struct
with a someFunc
field.
Having function pointer and monkey patching it is the one of doing it. But then when you multiple functions to mock, you will have a number function pointers and unnecessarily you will have to call function using the function pointer only.
The better and the recommended idea to have an interface and make your function part of the struct implementing the interface. Once done that, you can generate mocks using some nice tools available for go.
I have been using this:
mockgen -source myModule.go -package myPackage -destination myModuleMock.go
You can install it by:
got get github.com/golang/mock