4

I am mocking a method call as follows:

tctx.someMock.On("addProd",
        product.NewAddProductParamsWithContext(ctx).
            WithID("someid").
            WithCreateRequest(pro.CreateProdBody{
                creationDate: "someDate"  ,
            }), nil).
        Return(nil, nil)

which works fine.

Now, here, instead of passing a fixed value for the field creationDate, if I want to generalize it so it will work for any value passed, how can I achieve that? I am pretty new to Go, so not sure how to do this

the values for creationDate could be any value like - 2021-03-19T18:57:16.589Z or 2022-04-23T14:17:56.589Z etc. I just dont want to limit the mock call to work for a fixed value of creationDate, but I would like it to work for any date string passed

user1892775
  • 2,001
  • 6
  • 37
  • 58
  • By "any value" do you mean a string variable as opposed to the string constant `"someDate"`? Or do you mean a variable of any type, not just string? – mkopriva Mar 19 '21 at 19:40
  • @mkopriva it would be a string but the value can be anything. So, the mock call could apply for any creationDate and not just a fixed one. It can be 2021-03-19T18:57:16.589Z or 2022-04-23T14:17:56.589Z or any date strings like that. I dont want to limit the mock call to work for just one fixed date string, but it should work for any value passed there – user1892775 Mar 19 '21 at 19:43
  • 1
    If I understand you correctly, in essence you want the mock to ignore the `currentDate`, at most you want it to check if the field is set as opposed to empty, or maybe you want it to check that it matches a certain pattern, e.g. that of a timestamp. If that is indeed what you're looking for then whether or not it is possible depends entirely on the mock package that you're using, if that package doesn't support such a feature then you're out of luck. As an alternative approach however, you could make sure that the value is deterministic. – mkopriva Mar 19 '21 at 19:51
  • What package are you using for mocking? – mkopriva Mar 19 '21 at 19:54
  • What I see pretty much used in the project is github.com/stretchr/testify/mock. So, I believe its mockery – user1892775 Mar 19 '21 at 20:01

1 Answers1

7

Assuming you're using github.com/stretchr/testify/mock, you should be able to use mock.MatchedBy() to match on specific parts of the argument. For example:

tctx.someMock.On("addProd", mock.MatchedBy(func(i interface{}) bool {
    p := i.(*product.AddProductParams)
    return p.ID() == "someid"
})).Return(nil, nil)

However, I find this to be most useful when needing to take a different action depending on the input. If you're simply verifying addProd was called with a specific argument, consider asserting that instead:

tctx.someMock.On("addProd", mock.Anything).Return(nil, nil)

...

tctx.someMock.AssertCalled(t, "addProd", mock.MatchedBy(func(i interface{}) bool {
    p := i.(*product.AddProductParams)
    return p.ID() == "someid"
})).Return(nil, nil)
Gavin
  • 4,365
  • 1
  • 18
  • 27
  • Not very clear about the first method.We never set the ID parameter. So, p.ID will be empty. So the condition return p.ID() == "someid" will always return false. What am I missing? I just want to ingore the creationDate in the body, but I want to provide a fixed ID value for the mock – user1892775 Mar 19 '21 at 21:09
  • The `ID` method is just an example; although, **your** example includes `.WithID("someid")` as part of the argument, so I assumed that would be what you're trying to assert. You're missing the fact that you can use `mock.MatchedBy()` to assert the values on the fields you care about are correct, while ignoring the others... Notice that my example does no checking on the date field. `mock.MatchedBy()` lets you build a custom matcher for the argument at the given position e.g. the first argument in this example. – Gavin Mar 19 '21 at 21:50