Cuckoo icon indicating copy to clipboard operation
Cuckoo copied to clipboard

Why do I have to provide dependencies for my Mocks?

Open juliagarrigos opened this issue 7 years ago • 3 comments

Hi! I'm an Android developer that has been working on iOS for one year now. I'm used to libraries like mockito that create mocks automatically, I've been looking for something similar in iOS and finally I found this library. I wanted to first thank you for your work, this library saved my life 😄

I have a question related to the constructors of the mocks, if, for example, I have the class ConfigRepository with the following initializer:

 init(configLocalDataSource: ConfigLocalDataSource, configRemoteDataSource: ConfigRemoteDataSource)

I wouldn't expect the mock MockConfigRepository to also need the dependencies to be instantiated. I would expect MockConfigRepository() to work. However, I have to pass all the dependencies to the mocked class and I end up with something like this:

 mockConfigRepository = MockConfigRepository(configLocalDataSource: MockConfigLocalDataSource(userDefaultsDataSource: UserDefaultsDataSource(), timeDataSource: TimeDataSource()), configRemoteDataSource: MockConfigRemoteDataSource(urlSession: URLSession.shared))

Am I doing something wrong? maybe there is a way to avoid this but I couldn't find it... Or maybe there is a reason fot cuckoo to work like this, or plans to change it.

Thank you so much!

juliagarrigos avatar Jun 10 '18 09:06 juliagarrigos

Hello @juliagarrigos and welcome to Cuckoo community, we're glad you're here and that you like what we do.

Mocks generated by Cuckoo come in two "flavors". The "flavor" depends on what was the input for the specific mock. So in reality we have "class" and "protocol" mocks and their behavior differs a bit.

What you're experiencing is the "class mock" and that's because the input for the mock is a class. Due to the way Cuckoo works, we have to instantiate your "base" class when making an instance of the mock. That's why MockConfigRepository requires the dependencies to work.

If you want a "no-arg" initializer for generated mocks, they have to either be "protocol mocks", or the base class for the mock has to have a "no-arg" initializer itself. So making the ConfigRepository class into a protocol along with a real implementation would give you the behavior you're looking for.

A disadvantage of "protocol mocks" is that they don't allow "spies".

Let me know if there's anything I could help you with, or join our Slack team through: https://swiftkit.brightify.org

TadeasKriz avatar Jun 10 '18 19:06 TadeasKriz

Hello @TadeasKriz,

Thanks for the quick answer! I'll create protocols for my classes, I don't use spies anyway so it won't be a big problem for me (apart from the boilerplate of the Protocols).

Do you think it would be possible for cuckoo generator to check if there is a mock class for a dependency and inject it? I assume it wouldn't be easy because, to be able to check this you need all the mocks to be created...

Thanks!

juliagarrigos avatar Jun 13 '18 15:06 juliagarrigos

@juliagarrigos in our project we usually just instantiate the mock dependencies. It's handy as sometimes one of the dependencies needs to be a real instance and being able to see this in code without further abstraction is handy.

macduy avatar Sep 26 '18 18:09 macduy