How do we write unit test for a function using goroutine? considering inside function is being used with/without goroutine - unit-testing

so i have function without routine
func ContainsWithoutGoroutine() return {
someFunction()
return
}
and there is mock of someFunction
type DummyMock struct {
mock.mock
}
func(t *DummyMock) someFunction() {
//
}
to write the unit test for ContainsWithoutGoroutine we could easily mock someFunction and test it.
and now suppose i added a function with goroutine ContainsGoroutine
func ContainsGoroutine() return {
go func() {
someFunction()
}()
return
}
could not able to write unit test until we update the mock to something like this
type DummyMock struct {
mock.mock
Wg sync.WaitGroup
}
func(t *DummyMock) someFunction() {
defer t.Wg.Done()
//
}
and in the unit test of ContainsGoroutine need to add additional mock.Add(1) mock.Wg.Wait
after that unit test for ContainsGoroutine will work, but ContainsWithoutGoroutine will start failing
i know we could add same mock.Add(1) mock.Wg.Wait for the unit test of ContainsWithoutGoroutine to make it work , which i don't want to do that , As consider for the case where someFunction has been already being used in lot of places where there was no go routine and all that unit tests need to be changed.
is there a better way to structure this or maybe write unit test differently

Related

How to test a struct that calls its own method?

I have a struct:
type foo struct {
bar mockableInterface // some interface that I can mock
}
func (f *foo) DoSmth1() []interface{} {
return f.bar.Bar()
}
func (f *foo) DoSmth2() []interface{} {
res := f.DoSmth1()
//some code to test
}
Here I have no problem with mocking bar and testing DoSmth1(). But it's not obvious how to test DoSmth2().
Should I rewrite this method to make it testable or rewrite tests somehow?
#mkopriva recommended just to mock Bar() call in DoSmth2() test. But in this case I would rewrite tests for all method that calls DoSmth1() every time it changes. So I've come to the following solution. We can encapsulate this mock logic in one method:
func (s *TestSuite) ExpectDoSmth1(times int, in, out []interface{}) {
s.barMock.Expect().Bar(in...).Times(times).Return(out...)
}
This way we can change only this method if DoSmth1() implementation changes, till its API stays the same

Golang stretchr testify mock calls to a function within same class

I am pretty new to Golang and writing unit test for a function (I am using stretchr testify for mocks). This function however calls another function in same class. But when unit testing the first function, I want to mock the call to second function because I do not want it to call the second function in real. This was easy in Java, but I am not finding any useful information for this in Go. Here is some code snippet for my functions:
func (p *Prod) GetProducts(name string, request *prod.ProductRequest) (detail *prod.Department, err error) {
....
....
if err = p.getDetails(ctx, detail.Id); err != nil {
logger.Error(err)
return
}
...
...
}
func (p *Prod) GetDetails(name string, Id string) error {
....
....
}
As you can see here, GetProducts is the function that I am trying to unit test and this function calls GetDetails. I would like to mock the call to GetDetails. Is this possible in Go? Do we typically mock such function calls in Go. Is it recommended? If yes, whats the right way to do it?
In my test, I have:
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := &Prod{
...
ds: tt.fields.ds,
}
p.GetProducts("somestring", request)
})
}
This calls the function GetProducts. But now I don't know what changes to make so the call to GetDetails can be mocked. I would appreciate any help on this

Is DI(dependency injection) necessary for mocking dependencies in golang?

When I try to unit test a function as below, where extern_pkg is an external package to be mocked:
import "extern_pkg"
func MyFunc() {
...
extern_pkg.F()
}
func main() {
MyFunc()
}
I read a few blogs, and they all seem to achieve this by modifying prod code with dependency injection. For example, as below:
type exter interface {
F()
}
func MyFunc(e exter) {
...
e.F()
}
type extpkg struct{}
func (extpkg) F() {extern_pkg.F()}
func main() {
epkg := extpkg{}
MyFunc(epkg)
}
Then in test code, create a mock object that satisfies exter interface, and pass to MyFunc as parameter.
My question is:
If the MyFunc function contains many external packages to mock, do I need to DI each one as function parameters? Is it also true for any global variables the function depends on?
var global_var
func MyFunc() {
...
extern_pkg1.F()
...
extern_pkg2.G()
...
extern_pkg3.H()
...
global_var
}
Is there way to avoid modifying prod code?
Thanks!
Try use vars of func types and inject them. It is easier, lesser code and interfaces are not needed. See godif

assert_called_once() or assert_called_xyz().... equivalent?

It is important to me to be able to assert how many times a fake / mocked method is called in my tests and I'm wondering what is the best way to do this without using something like testify. In my case, the call to the mocked method is the result of some recursive call.
Lets say I have table driven tests with various animals, I want to assert that Hello is actually called for some tests but not for others. In some cases, it should be called more than once for given test (iterating over a slice).
Is it appropriate to just add a counter and make an assertion on that in my table driven test? It seems to me like maybe there is a better way to do this.
If I do add a counter to the hello method... where is it appropriate to deal with and check this. In the fake method itself or in the test etc?
type fakeFarmService struct {
abc.someFarmServiceInterface
}
func (f *fakeFarmService) Hello(ctx context.Context, in *abc.FarmRequest) (*abc.FarmResponse, error) {
if in.GetAnimal() == Monkey {
return &abc.HelloResponse{}, nil
}
return nil, errors.New("an error")
}
I've used the approach of counter on the struct and then asserting it inside the package level unit test multiple times in the past. Still, it's probably only until the level of package, when you would like to test such an internal assertions. I believe it's an accepted way of doing this in Go. Just be careful about properly synchronizing the access to the counter, if you decide to use a global variable or run the tests concurrently.
package main
import (
"fmt"
"sync"
"testing"
)
type fakeable interface {
Hello()
}
type fakeFarmService struct {
mu sync.Mutex
counter int
}
func (f *fakeFarmService) Hello() {
f.mu.Lock()
f.counter++
f.mu.Unlock()
}
func helloCaller(callee fakeable) {
callee.Hello()
}
func TestCallingTheHello(t *testing.T) {
fakeSvc := &fakeFarmService{}
helloCaller(fakeSvc)
helloCaller(fakeSvc)
// we expect that Hello method of fakeable was called 2 times
fakeSvc.mu.Lock()
defer fakeSvc.mu.Unlock()
if c := fakeSvc.counter; c != 2 {
t.Errorf("unexpected call count, want 2, got %d", c)
}
}
func main() {
TestCallingTheHello(&testing.T{})
}
https://play.golang.org/p/RXKuLKIZwc (test error won't work inside the playground)
Some good material on advanced testing in Go
Testing Techniques by Andrew Gerrand
NewStore TechTalk - Advanced Testing with Go by Mitchell Hashimoto

Golang: Replace function unit testing

I'm working with Golang, and currently I'm doing some fun unit test with Testify, my file look like this
type myStruct struct {
field_1 string
}
func (self *myStruct) writeFirst() {
//doing something
//modify field_1
self.writeSecond()
}
func (self *myStruct) writeSecond() {
//doing something
}
In this case I'm testing writeFirst() but I'm trying to replace writeSecond() because it is using http stuff that I don't want to use because it access to internet.
I think that use a second struct and set myStruct as anonymous field will be the solution, but it's not working because me second struct and myStruct have a diferent context.
In this case I can't use mocks cause writeSecond is a method of the struct.
My test case looks like this:
func TestWriteFirst(t *testing.T) {
myStc := myStruct{}
assert.Equal(t,"My response", myStc.field_1)
}
All that I want is testing writeFirst without pass to writeSecond()
To illustrate the kind of refactoring mentioned by Not-a-Golfer in the comments, you could consider calling your second function only on an instance that is an interface:
type F2er interface {
Func2()
}
type S struct{ _f2 F2er }
var s = &S{}
func (s *S) f2() F2er {
if s._f2 == nil {
return s
}
return s._f2
}
func (s *S) Func1() {
fmt.Println("s.Func1")
s.f2().Func2()
}
Here: Func1 calls Func2 on s.f2(), not directly s.
If nothing has been set in s, s.f2() returns... itself: s
if s._f2 was replaced by any other struct which implements Func2, s.f2() returns that instance instead of itself.
See a complete example in this playground script.
Output:
TestFunc1
s.Func1
s.Func2
TestFunc1bis
s.Func1
testS.Func2 <=== different Func2 call