0

I have a function in Go that takes an input argument, modifies it, and finally returns it. To be concrete, this function persists some data in DB using the Bun ORM and returns the persisted entity. That said, I have a unit test where I mock this function, and would need the mocked function to return the variable it receives as an argument. Let's better explain it with a fairly simple example:

package doer

type Something struct {
    Message string
}

type Doer interface {
    DoSomething(s *Something) *Something
}
func TestDoer(t *testing.T) {
    var response *doer.Something

    request := &doer.Something{
        Message: "foo",
    }

    sut := mocks.Doer{}
    sut.On("DoSomething", mock.Anything).Run(func(args mock.Arguments) {
        response = args.Get(0).(*doer.Something)
    }).Return(response)

    r := sut.DoSomething(request)

    assert.Equal(t, request.Message, r.Message)
}

The issue I'm facing here is that the assertion triggers a panic because r is nil. After thinking about it, I think this happens because Return is executed before the function passed to Run and at this point response is nil, so it always returns nil. That said, I would like to know if there is any way of achieving what I want. Please take into account that I need to honor the interface, I already know that I could just rely on the pointer passed to the function as an input argument and get rid of the return value, but I need to stick to this contract.

I'm using testify as the mocking framework

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
beni0888
  • 1,050
  • 1
  • 12
  • 40
  • 1
    `response := new(doer.Something)` and inside the callback `*response = *(args.Get(0).(*doer.Something))` – mkopriva May 18 '23 at 11:23
  • And btw. with the [`gomock`](https://pkg.go.dev/github.com/golang/mock@v1.6.0/gomock) package you can do [`DoAndReturn`](https://pkg.go.dev/github.com/golang/mock@v1.6.0/gomock#Call.DoAndReturn) to return the value from the callback. I don't know what mocking framework you're using but perhaps it has something analogous. – mkopriva May 18 '23 at 11:30
  • What's the point of this test? It seems like you're just asserting you set up a mock correctly, thus not really testing `Doer`... – Gavin May 18 '23 at 13:52
  • @Gavin the test is not real, it's just an example to show what I want to achieve, but I want to achieve that in real-world more complex use case. – beni0888 May 18 '23 at 14:35
  • @mkopriva What you propose in your comment definitely make the trick. Would you mind posting it in an answer so I can mark it as the solution? – beni0888 May 18 '23 at 14:37

0 Answers0