gojuno / minimock

Powerful mock generation tool for Go programming language
MIT License
577 stars 38 forks source link

Generation for interfaces with no methods #48

Closed rbUUbr closed 6 months ago

rbUUbr commented 4 years ago

Hi! Thanks for this library, it really helped me to understand mocks fully! Hope it will get some new awesome features. So, I have an application that uses GitHub.com/olivere/elastic (We are using a lot from this library), that's why I tried to mock all interfaces from it, in my generate.go: //go:generate minimock -i github.com/olivere/elastic.* -o ./ And I'm getting something like:

minimock: ./database_mock_test.go
minimock: ./smoothing_model_mock_test.go
minimock: ./candidate_generator_mock_test.go
minimock: ./rescorer_mock_test.go
minimock: ./suggester_mock_test.go
minimock: ./backoff_mock_test.go
minimock: ./score_function_mock_test.go
minimock: ./aggregation_mock_test.go
minimock: ./composite_aggregation_values_source_mock_test.go
minimock: ./query_mock_test.go
minimock: ./bulkable_request_mock_test.go
minimock: ./sorter_mock_test.go
minimock: ./doer_mock_test.go
minimock: ./alias_action_mock_test.go
minimock: ./retrier_mock_test.go
minimock: interface has no methods

That's why I've failed to generate mocks for the rest of the interfaces. I think it can be great to just add warning message and continue the generation process. WDYT about it?

hexdigest commented 4 years ago

Hi @rbUUbr !

Thanks for the issue, it certainly needs to be fixed.

rbUUbr commented 4 years ago

I will take a look on it, because it is important for me :D

hexdigest commented 4 years ago

Ok, PRs are always welcome!

The only thing I wanted to tell you is that if you generate mocks using interfaces from some 3rd party library you're probably doing something wrong (not a go way).

Interfaces should be defined in your packages and third party library is just an implementation of your interfaces (this is called duck typing). Therefore, you have to generate mocks for your interfaces and maybe it's not necessarily to declare an empty interface in your package. Just interfaces that you depend on. You definitely don't have any dependencies on empty interfaces, probably you depend just on few interfaces from this lib.

So think a bit about reorganizing your code first and then you won't have this problem at all.

rbUUbr commented 4 years ago

wow, such a great advice, thanks! Just for example, what if my library has Doer interface, that just performs HTTP requests and it can be used to mock Elastic client. Is it ok to mock such interface?

hexdigest commented 4 years ago

Is it ok to mock such interface?

Maybe I misunderstood your question but If you want to mock the Elastic client that you use in your library then you need to create an interface with methods of Elastic client you use and make this interface your dependency. Once you described your dependency via the interface you can generate mock for this interface. There's no need to generate mock for HTTP client if you want to mock the client for Elastic.

Let's say you have the following call chain: Your project -> Elastic client -> HTTP client

If you want to mock HTTP client in this case for mocking the behavior of Elastic client then you doing it wrong. Instead in your project you have to declare an interface like "ElasticClient" with the only methods your project really uses from Elastic client and then generate mock for ElasticClient interface to test your project.

rbUUbr commented 4 years ago

hmmm ,very interesting. I want to provide full example, because it is very interesting as for me: I'm using https://github.com/olivere/elastic for ElasticSearch. And In my tests I want to mock calls to ElasticSearch real server, that's why I'm trying to mock: https://github.com/olivere/elastic/blob/release-branch.v7/client.go#L105 How do you think, is it okay? In my application's code I have struct with field client with type elastic.Client (client struct from ES library)

hexdigest commented 4 years ago

How do you think, is it okay? In my application's code I have struct with field client with type elastic.Client (client struct from ES library)

No it's not ok. You have to define interface in your code that will be implemented (via duck typing) by the olivere/elastic. And then you have to mock the interface YOU defined.

hexdigest commented 6 months ago

Hey @rbUUbr

This one is fixed in v3.3.1