How to Mock only specific method in Golang - unit-testing

I am fairly new to golang and I am struggling with a simple task.
I have the following class in golang
type struct A {
}
func (s *A) GetFirst() {
s.getSecond()
}
func (s *A) getSecond() {
// do something
}
And I want to write some tests for it however for that I need to override getSecond(). I attempted to do the following in my test files
type Ai interface {
getSecond()
}
type testA struct {
A
}
func (s *testA) getSecond() {
// do nothing
}
func TestA(t *testing.T) {
a := &A{}
t := &testA{A: a}
t.GetFirst()
}
The idea here is to expose A getSecond() method to an interface and override by using embedding however this does not seem to work. The test still calls the original implementation of getSecond() instead of my mocked one.
One solution would of course be to create a proper interface for A which contains getFirst() and getSecond() and then in the test create a struct implementing both where getFirst() call the original implementation and getSecond() a dummy however I feel this is cumbersome and not the correct way of doing things.
Another possibility would be to assign getSecond() in the real implementation to a variable and override the variable in test but I also feel it is a bit strange to do this just for a simple override.
Am I going all wrong about this? Is there any way simpler way to do this using golang?

You can't really override methods in golang as per this answer. However, as you point out you can have a separate interface for the "getSecond method" and have one implementation in your test cases and one implementation in your actual code.
type s interface{
getSecond()
}
type A struct{
s
}
type a struct{
}
func (s *A) GetFirst() {
s.getSecond()
}
func (s a) getSecond() {
// do something
}
//Use a
A{a{}}
Then in Test have a different implementation of 'a'
type ta struct {
}
func (s ta) getSecond() {
// do nothing
}
A{ta{}}

mockcompose (https://github.com/kelveny/mockcompose) was created by me to address exactly the problem.
Class in Go is not the first class citizen, for those who come from other language worlds (i.e. Java), lack of ability for mocking sibling methods sometimes bothers.
Say you have a class foo
package foo
type foo struct {
name string
}
func (f *foo) Foo() string {
if f.Bar() {
return "Overriden with Bar"
}
return f.name
}
func (f *foo) Bar() bool {
if f.name == "bar" {
return true
}
return false
}
You want to test Foo() method, however, when Foo() calls Bar(), you want Bar() to be mocked.
With mockcompose, you can first configure go generate and let mockcompose generate plumbing things for you.
mocks.go
//go:generate mockcompose -n testFoo -c foo -real Foo -mock Bar
package foo
mockcompose will then generate code: mockc_testFoo_test.go
//
// CODE GENERATED AUTOMATICALLY WITH github.com/kelveny/mockcompose
// THIS FILE SHOULD NOT BE EDITED BY HAND
//
package foo
import (
"github.com/stretchr/testify/mock"
)
type testFoo struct {
foo
mock.Mock
}
func (f *testFoo) Foo() string {
if f.Bar() {
return "Overriden with Bar"
}
return f.name
}
func (m *testFoo) Bar() bool {
_mc_ret := m.Called()
var _r0 bool
if _rfn, ok := _mc_ret.Get(0).(func() bool); ok {
_r0 = _rfn()
} else {
if _mc_ret.Get(0) != nil {
_r0 = _mc_ret.Get(0).(bool)
}
}
return _r0
}
Now, all you need to do is just to write your unit testing logic as you do in other languages (i.e. Java), for example:
func TestFoo(t *testing.T) {
assert := require.New(t)
fooObj := &testFoo{}
// Mock sibling method Bar()
fooObj.On("Bar").Return(false)
s := fooObj.Foo()
assert.True(s == "")
}
For details, please check out https://github.com/kelveny/mockcompose, mockcompose can also help you test regular functions with callouts to imported functions from other packages.

I think there are at least two alternatives.
Use always a function field
When the function mocked is something not related to the struct I'm mocking, maybe a third party function, or something written from another component of my application.
I will assign the real working one when initializing the service or the mocked one on the tests.
// service.go
type MyService struct {
getRandomID func() string
}
type Car struct {
ID string
Name string
}
func (s *MyService) NewCar() (*Car, error) {
car := Car{
ID: s.getRandomID(),
Name: "ThisCar",
}
return &car, nil
}
// service_test.go
func newIDsForTests() func() string {
i := 0
return func() string {
i++
return fmt.Sprintf("%024d", i)
}
}
func TestNewCar(t *testing.T) {
s := MyService{
getRandomID: newIDsForTests(),
}
actual, err := s.NewCar()
if err != nil {
panic(err)
}
expected := Car{ID: "000000000000000000000001", Name: "ThisCar"}
if *actual != expected {
panic("cars don't match")
}
}
The Go Playground working example
Use a function field only when mocking
When the function to be mocked is something really related to the struct I'm working with, that is part of this component.
I will always use the real working, and assign a mock function when needed for the tests.
While I think this solution is quite ugly, I also think that is for sure easily to use and to maintain, while also let you unit test your code at 100%!
My idea is to add a field mockedGetSecond to the struct, and to set its value only in the tests where you want to mock the real getSecond. In the real implementation you have to add a check of course, that if this func isn't nil, it must be used.
This is probably not a good pattern, or something I would like to use often, but I think I'll will use it to mock a function that do a lot of logic (and a lot of db calls, and need various input, ...) and is often called in the functions in the same service.
// service.go
import (
"fmt"
"testing"
)
type MyService struct {
mockedGetSecond func() (string, error)
}
func (s *MyService) GetFirst() error {
secondVal, err := s.getSecond()
if err != nil {
return err
}
fmt.Println("getSecond returned: ", secondVal)
return nil
}
func (s *MyService) getSecond() (string, error) {
if s.mockedGetSecond != nil {
return s.mockedGetSecond()
}
// very complex function
return "real", nil
}
// service_test.go
func TestGetFirst(t *testing.T) {
myService := MyService{
mockedGetSecond: func() (string, error) {
return "mocked", nil
},
}
err := myService.GetFirst()
if err != nil {
panic(err)
}
}
func TestGetSecond(t *testing.T) {
myService := MyService{}
actual, err := myService.getSecond()
if err != nil {
panic(err)
}
if actual != "real" {
panic("I would expect 'real'")
}
}
The Go Playground working example
=== RUN TestGetFirst
getSecond returned: mocked
--- PASS: TestGetFirst (0.00s)
=== RUN TestGetSecond
--- PASS: TestGetSecond (0.00s)
PASS

In case someone ends up here on a similar dive down the rabbit hole: I wanted to mock a function called by another function to ensure it's called x times under specific conditions, such as you would do with Jest for example. I wanted to keep the program code as test-agnostic as possible, and having had little success with receiver methods and overriding functions in interfaces I opted for simply passing a function reference as an argument. So if you aren't dead set on an OOP style approach:
// app.go
type SubDoer func(string) string
func SubDo(something string) string {
...
return something
}
func DoHandler(somethings []Something) string {
return Do(somethings, SubDo)
}
func Do(somethings []Something, subDoer SubDoer) string {
...
subDoer(something)
return somethingElse
}
The DoHandler() function gives us a wrapper to call Do() with the actual SubDo() implementation, and we can unit test Do() with a mocked SubDo() by skipping the handler function:
// app_test.go
type MockDoer struct {
counter int
}
func (m *MockDoer) SubDo(string) string {
m.counter++
return "something"
}
// Calls the mocked function from Do()
func TestDoWithMockedSubDo(t *testing.T) {
mock := &MockDoer{}
...
assert.Equal(t, "something", Do(somethings, mock.SubDo))
assert.Equal(t, mock.counter, xAmount)
}
// Calls DoHandler() which calls Do() with the unmocked SubDo()
func TestDo(t *testing.T) {
...
assert.Equal(t, "something else", DoHandler(somethings))
}
// SubDo() is unaffected by the mocks
func TestSubDo(t *testing.T) {
...
assert.Equal(t, "a thing", SubDo(something))
}

Related

Golang Unit Test Mock method of nested struct

I want to mock a method of a nested struct. I have tried to define an interface and make the Mock implement it, but I could not get it working.
This is the struct I want to test:
type OuterThing struct {
innerThing *InnerThing
}
func (a *OuterThing) doLotsOfStuff() {
println("i am doing")
u, err := a.innerThing.DoStuff("lots of stuff")
if err != nil {
println("ran into an error, also doing some logic")
}
println("and more", u)
}
The nested struct, of which I want to mock its DoStuff() function, looks like this:
type InnerThing struct {
name string
}
func (b *InnerThing) DoStuff(x string) (uint64, error) {
println("i want to mock this method")
return 0, nil
}
Little side twist: I can not change the code of these structs and their methods.
To make my point a bit more clear i have written this test:
func TestDoLotsOfStuff(t *testing.T) {
testCases := []struct {
name string
structUnderTest *OuterThing
}{
{
name: "happy case",
structUnderTest: &OuterThing{
innerThing: &InnerThing{name: "I am the inner thing."},
},
},
{
name: "error case",
structUnderTest: &OuterThing{
innerThing: &InnerThing{name: "i should be a mock with a mocked DoStuff function"},
},
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
testCase.structUnderTest.doLotsOfStuff()
// assertions
})
}
}
I am quite familiar with Java and Mockito and this would be a pretty trivial task. I know Go has lots of differences with its implicit interfaces and no classes et cetera, but is this really such an uncommon usecase?
You can do it by using an Interface and Dependency Injection.
Let's say, you have an Interface called Inner that contains the DoStuff() method. The OuterThing struct should contain this Interface instead of the struct InnerThing. Now, you can use dependency injection to pass the Inner Interface to this OuterThing struct.
type Inner interface {
DoStuff(string) (uint64, error)
}
type OuterThing struct {
innerThing Inner
}
func NewOuterThing(in Inner) *OuterThing {
return &OuterThing{
innerThing: in,
}
}
Now, in the test, you can create the mockInnerThing struct and implement the mock DoStuff() method and pass the mockInnerThing to the OuterThing struct.
type MockInnerThing struct {
name string
}
func NewMockInnerThing(name string) *MockInnerThing {
return &MockInnerThing{
name: name,
}
}
func (b *MockInnerThing) DoStuff(x string) (uint64, error) {
println("Mock!")
return 0, nil
}
func TestDoLotsOfStuff(t *testing.T) {
mit := NewMockInnerThing("Test")
ot := NewOuterThing(mit)
ot.doLotsOfStuff()
}

Go mocking with interfaces for testing

I'm pretty new with Go, and I'm coming from OOP languages. Now the concept seems quite different in go of interfaces and classes.
I was wondering how mocking would work in case of testing. The confusion I'm having is whether ok to use struct as a classes and if the approach below is how you suppose to do? Assuming that DefaultArticlesRepository would be for real data and MockArticlesRepository for mocking it.
type ArticlesRepository interface {
GetArticleSections() []ArticleSectionResponse
}
type DefaultArticlesRepository struct{}
type MockArticlesRepository struct{}
func (repository DefaultArticlesRepository) GetArticleSections() []ArticleSectionResponse {
return []ArticleSectionResponse{
{
Title: "Default response",
Tag: "Default Tag",
},
}
}
func (repository MockArticlesRepository) GetArticleSections() []ArticleSectionResponse {
return []ArticleSectionResponse{
{
Title: "Mock response",
Tag: "Mock Tag",
},
}
}
func ArticleSectionsProvider(v ArticlesRepository) ArticlesRepository {
return v
}
func TestFoo(t *testing.T) {
realProvider := ArticleSectionsProvider(DefaultArticlesRepository{})
mockProvider := ArticleSectionsProvider(MockArticlesRepository{})
assert.Equal(t, realProvider.GetArticleSections(), []ArticleSectionResponse{
{
Title: "Default response",
Tag: "Default Tag",
},
})
assert.Equal(t, mockProvider.GetArticleSections(), []ArticleSectionResponse{
{
Title: "Mock response",
Tag: "Mock Tag",
},
})
}
Firstly, I suggest you to use https://github.com/vektra/mockery for generating mock structs automatically based on interfaces. Implementing a mock struct like your is ok but I think it just wastes your time and effort if you do not really need a very special behavior for that struct.
Secondly, we do not need to test mock structs like you do in your code.
assert.Equal(t, mockProvider.GetArticleSections(), []ArticleSectionResponse{
{
Title: "Mock response",
Tag: "Mock Tag",
},
})
So when we use mock structs, suppose struct a is a dependency of struct b. For example:
type A interface {
DoTask() bool
}
type a struct {}
func (sa *a) DoTask() bool {
return true
}
type b struct {
a A
}
func (sb *b) DoSomething() bool {
//Do some logic
sb.a.DoTask();
//Do some logic
return true;
}
And you want to test function DoSomething of struct b. Of course you do not care and do not want to test function DoTask of struct a in this case. Then you just simply provide a mock of struct a to struct b in the test. This mock also helps you avoid to deal with any struggle related to struct a in testing struct b.
Now your test should be like this:
func (s *TestSuiteOfStructB) TestDoSomething_NoError() {
//Suppose that mockedOfA is a mock of struct a
instanceOfB := b{a: mockedOfA}
mockedOfA.On("DoTask").Return(true)
actualResult := instanceOfB.DoSomething()
s.Equal(true, actualResult)
}
The last, this is just a small thing but do not see a clear responsibility of your ArticleSectionsProvider.

Mockito: Mock an invokable param

Kotlin function to test:
suspend fun <T: Any> handleSomething(call: suspend () -> Result<T>) {
if (call.invoke() == "Something") {
...
}
else {
...
}
}
I want to mock call here.
Usually I mock like:
val call = Mockito.mock(SomeClass::class.java)
But I don't know for param as function like this
Original answer: https://stackoverflow.com/a/53306974/11377112
This is how you mock a lambda function:
val call = Mockito.mock<suspend () -> Result<T>>()
handleSomething(call)
verify(call)()
// Or verify(call).invoke(any()) to be explicit

Mocking Java 8 lamba function with Mockito 2

I am using JDBI 3 and have written the following utility function.
public class JdbiHelper {
// ...
public <T, DAO> T fetch(final Function<DAO, T> function, Class<DAO> daoClass) {
return dbi.withHandle(handle -> {
final DAO dao = handle.attach(daoClass);
try {
return function.apply(dao);
}
finally {
handle.close();
}
});
}
}
which I can call in methods like this
public Optional<Account> findByEmailAddress(final String emailAddress) {
if (!exists(emailAddress))
return Optional.empty();
return jdbiHelper.fetch(dao -> ofNullable(dao.selectByEmailAddress(emailAddress)), AccountDAO.class);
}
private boolean exists(final String emailAddress) {
return jdbiHelper.fetch(dao -> dao.count(emailAddress) > 0, AccountDAO.class);
}
I am trying to write a test for the findByEmailAddress mocking jdbiHelper using Mockito 2 but cannot work out how to mock the dao -> part of the method.
I've tried using jdbiHelper.fetch(any(Function.class), eq(AccountDAO.class)) but as there are two different expectations of what to return it fails trying to cast one or the other.
Passing in a mocked Function causes a NPE as the dao param is null.

How can I mock structure method in same structure method in Golang?

I have troubles with mocking.. I have same code:
type OtherInterface interface {
Do() error
}
type MyInterface interface {
MethodA() error
MethodB() error
}
type MyStruct struct {
OtherStruct OtherInterface
}
func(s *MyStruct) MethodA() error {
return s.MethodB()
}
func(s *MyStruct) MethodB() error {
return s.OtherStruct.Do()
}
And test code of MethodB:
type MockOtherStruct struct {
Do_Error error
}
func (t *MockOtherStruct) Do() error {return t.Do_Error}
TestMyStruct_MethodB(t *testing.B) {
expectedError = nil
mos := &MockOtherStruct{
Do_Error: nil
}
ms := MyStruct{
OtherStruct: mos,
}
err := ms.MethodB()
if err != expectedError {
t.Fatal(err)
}
}
But how can I test MethodA?
Yes, I can also mock OtherStruct and use not mocked MethodB, but in big structs I can have many fields with other structs, but use one internal method..