1

I have the file util.go:

func Foo(service *SomeService) error {
    return helper(service)
}

func helper(service *SomeService) error {
    ...
}

I'm writing unit tests using testify, starting with Foo. I want to:

  1. mock helper
  2. assert mocked helper was called 1 time

I saw some promising solutions at https://stackoverflow.com/a/19168875/1661745, but not sure about them:

Method 1: pass helper as parameter of Foo. My doubt: testify needs a Mock struct to AssertNumberOfCalls, and here there is no struct.

Method 2: create a struct for Foo. My doubt: I don't know if it makes sense to make a struct for utils. Also requires more refactoring since callers of Foo would need a utils struct.

What's the best way to do this?

onepiece
  • 3,279
  • 8
  • 44
  • 63
  • You should not mock at all. Write proper tests. If `helper` has no side effects there is no need to check that it was called exactly once. If it has side effects: Test that they happened in the expected way. Take a look at how the stdlib does testing. – Volker Jun 05 '20 at 05:42
  • `helper` does have side affects (call service/DB). I'm coming from Java world, where the dependencies would be mocked for unit tests. I don't want to have to set those dependencies up. – onepiece Jun 05 '20 at 06:00
  • When unit testing `Foo`, I want to mock `helper` since I plan to have separate unit tests for `helper`. – onepiece Jun 05 '20 at 06:08
  • 1
    Proper unit testing in Go is not done like unit testing in Java. Write tests for helper and write tests for Foo but unless your test of foo needs to call a different helper (not in your case as no side effects): Do not mock it. Really. Stopp that. It might (or might not) be the proper way of testing in Java but it is not the right thing to do in Go. – Volker Jun 05 '20 at 06:32
  • As @Volker said, you don't need to mock helper. You can write test for helper. If helper passed the test, so Foo would. – Billy Yuan Jun 05 '20 at 09:49

1 Answers1

-1

If you just want to test the args being called in helper, this is an approach that I have been using. The same test will also prove that your helper was called exactly once.

    // Code

    var originalFn = func(arg1, arg2 string) {
        ...
    }


    func Foo() {
        originalFn(arg1,arg2)
    }

    // Tests

    func TestFoo(t *testing.T) {
        tempFn := originalFn
        var fnArgs []string
        originalFn = func(arg1, arg2) {
            fnArgs = append(fnArgs, []string{arg1, arg2})
        }
        defer originalFn = tempFn

        tests := []struct{
            expected []string
        }{
            {
                expected: []string{"arg1", "arg2"},
            },
        }

        for _, tt:= range tests {
            fnArgs := make([]string, 0)
            Foo()
            assert.Equal(t, tt.expected, fnArgs)
        }
    }
poWar
  • 745
  • 6
  • 15