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.
The following code works:
protocol GenericStorage {
associatedtype Value
func store(value: Value)
}
protocol DataStorage {
func store(value: Data)
}
struct StringStorage: GenericStorage {
typealias Value = String
let wrapped: DataStorage
func convert(_ str: String) -> Data {
return Data(str.utf8)
}
func store(value: String) {
wrapped.store(value: convert(value))
}
}
Can I use the GenericStorage protocol with an associated type of Data for the wrapped argument in StringStorage in order to avoid the redundant DataStorage protocol altogether?
I expect something like the following code (not working):
protocol GenericStorage {
associatedtype Value
func store(value: Value)
}
struct StringStorage: GenericStorage {
typealias Value = String
let wrapped: GenericStorage where Value = Data
func convert(_ str: String) -> Data {
return Data(str.utf8)
}
func store(value: String) {
wrapped.store(value: convert(value))
}
}
Based on the comments, you would need to turn GenericStorage into a generic protocol. However, at the moment, you cannot make a protocol generic. You can only add type constraints to the associatedType (introduced in Swift4) or to the functions of the protocol.
For more information on generic protocols, see the Generics Manifesto.
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.
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))
}
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..