golang / mock

GoMock is a mocking framework for the Go programming language.
Apache License 2.0
9.3k stars 611 forks source link

Error output is ambiguous for equivalent values with different types #190

Closed bradwilzon closed 3 years ago

bradwilzon commented 6 years ago

https://github.com/golang/mock/blob/22bbf0ddf08105dfa364d0a2fa619dfa71014af5/gomock/matchers.go#L53

When printing output for matched errors, if the expected and actual value have different types, either a special message should be printed (ie. expected value type does not match actual value type), or simply print the type with the output.

My confusing error output:

Expected call at mytest.go:467 doesn't match the argument at index 1.
Got: 8
Want: is equal to 8

In this case, I was using a const val = 8 which is resolved to an int. The const is used in the innards of a struct that expects an int32 (so the const is correctly casted). The const is then passed as the parameter to a method mocked by EXPECT() that originally takes an int32, but the mock version of the method takes an interface{}. Therefore, in the second case, the const is never casted correctly to int32 and causes a type mismatch further down the call path.

The long story short is, it's possible for gomock to print equivalent values without type information.

codyoss commented 4 years ago

I agree that this seems like something we should do. I would be willing to look at PR for this. Types might add a bit of noise if always there. Could hide that info behind a verbose flag as well... If you liked this issue feel free to share your thoughts.

codyoss commented 4 years ago

Another usecase from #267

When comparing an expected arg with a nil slice to an actual arg with a zero length slice, mock concludes the two do not match, however, the output for 'want' and 'got' is exactly the same for the nil/emtpy slice and does not indicate where the mismatch occurred.

Example:

--- FAIL: TestNilVsEmpty (0.00s)
    example_test.go:24: Unexpected call to *mock_example.MockThing.Apply([0xc0000900a0]) at /usr/local/google/home/briankennedy/golang/work/src/github.com/briantkennedy/mockbug/pkg/mock_example/mock_thing.go:39 because: 
        Expected call at /usr/local/google/home/briankennedy/golang/work/src/github.com/briantkennedy/mockbug/pkg/example/example_test.go:19 doesn't match the argument at index 0.
        Got: &{[]}
        Want: is equal to &{[]}
    asm_amd64.s:522: missing call(s) to *mock_example.MockThing.Apply(is equal to &{[]}) /usr/local/google/home/briankennedy/golang/work/src/github.com/briantkennedy/mockbug/pkg/example/example_test.go:19
    asm_amd64.s:522: aborting test due to missing call(s)
FAIL
FAIL    github.com/briantkennedy/mockbug/pkg/example    0.021s
?       github.com/briantkennedy/mockbug/pkg/mock_example   [no test files]

repository with code that reproduces issue: https://github.com/briantkennedy/mockbug

cc: @briantkennedy

tommyjcarpenter commented 4 years ago

I hit this exact issue today. In my case, I was using a simple type alias type m bson.M for brevity, which we do in the codebase, however gomock seems not happy with it, but the error message was very confusing until I found this issue:

      Unexpected call to *mock.MockCollection.Find([context.TODO map[cluster_id:<nil>]]) at /Users/tc677g/Development/go/src/app_flotilla/db/mock/db.go:150 because:
      expected call at  xxx
      Got: map[cluster_id:<nil>]
      Want: is equal to map[cluster_id:<nil>]

As someone fairly new to go mocking, this really stumped me for awhile

Maybe the answer to this, before printing the statement, is to check the value string representations, and if they are equal, print the types of the got and expected?

xavierpjb commented 3 years ago

Got the same issue

Unexpected call to *artifact.MockIRepositoryHandler.RetrieveList([1 5]) at /Users/xavierjeanbaptiste/Developer/workspace/projects/Mural/muralDevice/artifact/artifact.go:59 because: 
        expected call at /Users/xavierjeanbaptiste/Developer/workspace/projects/Mural/muralDevice/artifact/artifact_test.go:42 doesn't match the argument at index 0.
        Got: 1
        Want: is equal to 1

Any update?

For those looking for a temp fix, changing the autogenerated mock file's method input param type from "interface{}" to desired type fixed is for me. This does mean that when you regenerate the mock files you'll also need to make that change again.

csvwolf commented 3 years ago

@xapatjb4 The same problem, any good workaround?

I use the following methods to fix it, but looks like a bad one:

mock.Expect().Func(int32(1)).Return(...) // Can't use number 1 directly since default type is int
iurydias commented 3 years ago

Same issue here :( Not matching equivalent values with different types

codyoss commented 3 years ago

@iurydias Are you using v1.6.0? If so this should be fixed.

iurydias commented 3 years ago

v1.3.1 I just resolved forcing type declaration to param like int64(var).. I will update the version anyway...

Edit: I updated and now we can see the type on output, so much better!

alexandre-slp commented 2 years ago

I just got the same error here:

=== RUN   TestInitializeHealthCheckService_InitPaths
    route.go:12: Unexpected call to *mocks.MockRouter.GET([/healthcheck 0x625020]) at app/api/healthcheck/route.go:12 because: 
        expected call at app/api/healthcheck/route_test.go:18 doesn't match the argument at index 1.
        Got: 0x625020 (func(*fasthttp.RequestCtx))
        Want: is equal to 0x625020 (func(*fasthttp.RequestCtx))
    controller.go:269: missing call(s) to *mocks.MockRouter.GET(is equal to /healthcheck (string), is equal to 0x625020 (func(*fasthttp.RequestCtx))) app/api/healthcheck/route_test.go:18
    controller.go:269: aborting test due to missing call(s)
--- FAIL: TestInitializeHealthCheckService_InitPaths (0.00s)

FAIL

Process finished with the exit code 1

version: github.com/golang/mock v1.6.0

@codyoss, can you help me? Am I doing something wrong?

seven-yu commented 2 years ago

I just got the same error here version: github.com/golang/mock v1.6.0

codyoss commented 2 years ago

Please open a new issue with code to reproduce.