How can I mock structure method in same structure method in Golang? - unit-testing

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..

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.

How to Mock only specific method in Golang

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))
}

how to expect pointer argument which is created later

I have such group -> element to add/remove, with code snippt:
// production code:
Group::add(Element* e) {...};
Group::remove(Element* e) {...};
ElementDerived::ElementDerived(Group* group){ group->add(this);}
ElementDerived::~ElementDerived(Group* group){ group->remove(this);}
whenever i want to test the class ElementDerived, i have to do the following in the setup/teardown. However, how can I set the argument expectation explicitly without _?
// test code:
struct Test_ElementDerived : public ::testing::Test {
void SetUp() override {
ElementDerived* p = nullptr;
EXPECT_CALL(group, add(_)) // how to set expection on the pointer argument?
.WillOnce(Invoke([&p](auto base_ptr) {
p = static_cast<ElementDerived*>(base_ptr);
}));
sut = std::make_unique<ElementDerived>(&group);
}
void TearDown() override {
EXPECT_CALL(group, remove(sut.get()));
}
MockGroup group{};
std::unique_ptr<ElementDerived> sut;
};
You can do this:
Element* p = nullptr;
EXPECT_CALL(group, add(_)).WillOnce(SaveArg<0>(&p));
sut = std::make_unique<ElementDerived>(&group);
ASSERT_EQ(p, static_cast<Element*>(sut.get()));
This does not differ much from what you just did. To replace _ with some matcher - you would have to know the pointer - the only way to achieve that is to use placement new:
struct DestructCaller {
template <typename T> void operator()(T* ptr)
{
if (ptr) ptr->~T();
}
};
std::aligned_storage_t<sizeof(ElementDerived), alignof(ElementDerived)> sut_storage;
std::unique_ptr<ElementDerived, DestructCaller> sut;
void SetUp() override
{
EXPECT_CALL(group, add((ElementDerived*)&sut_storage));
sut.reset(new (&sut_storage) ElementDerived(&group));
}
Or similar concept with unrestricted union:
union
{
ElementDerived sut;
};
void SetUp() override
{
EXPECT_CALL(group, add(&sut));
new (&sut) ElementDerived(&group);
}
void TearDown() override
{
EXPECT_CALL(group, remove(&sut));
sut.~ElementDerived();
}
In my personal opinion - a way with SaveArg and ASSERT_EQ is more readable.

Is a macro to catch a set of exceptions at different places fine?

I have a set of functions and need to convert potentially thrown exceptions into
error codes.
To this end I have wrapped the actual calls with try/catch statements:
int f_with_error_codes()
{
try {
f(); // wrapped function call
return E_SUCCESS;
}
catch (error1&) {
return E_ERROR1;
}
catch (error2&) {
return E_ERROR2;
}
}
int g_with_error_codes(int a);
{
try {
G g(a); // wrapped expressions
g.print();
return E_SUCCESS;
}
catch (error1&) {
return E_ERROR1;
}
catch (error2&) {
return E_ERROR2;
}
}
...
These catch statmements repeat themselves. Additionally whenever a new exception
is added a new catch clause has to be added to every call wrapper.
Is a macro like below for replacing the catch statements appropriate?
#define CATCH_ALL_EXCEPTIONS \
catch (error1&) { \
return E_ERROR1; \
} \
catch (error2&) { \
return E_ERROR2; \
}
Which would results in:
int f_with_error_codes()
{
try {
f(); // the wrapped
return E_SUCCESS;
}
CATCH_ALL_EXCEPTIONS
You can use a function instead of a macro like this:
int f_with_error_codes()
{
try {
f(); // wrapped function call
return E_SUCCESS;
}
catch (...) {
return error_code();
}
}
int error_code()
{
try {
throw;
}
catch (error1&) {
return E_ERROR1;
}
catch (error2&) {
return E_ERROR2;
}
}
For your case, you don't need any macro.
Just a simple base class containing virtual function will be sufficient.
class error : public std::exception { // std::exception is your wish
const char* what () throw(); // needed if std::exception is based
virtual int GetValue () const = 0; // <--- This is the core part
}
Now, inherit this class with all the error# classes:
class error1 : public error {
virtual int GetValue () const { return E_ERROR1; } // <--- override
};
// ...
Finally your code is as easy as this:
void f_with_error_codes()
{
try {
f(); // wrapped function call
return E_SUCCESS;
}
catch (error& e) { // <--- base handle
return e.GetValue();
}
}
Don't bother about the cost of virtual function here. Because it's minimal and also exceptions are rare events; a very small cost of virtualness is worth for making your code maintainable and extendable.