Koin: Injecting Objects within Activity tests

Created on 4 Jan 2019  Â·  3Comments  Â·  Source: InsertKoinIO/koin

Describe the bug
After I upgraded to Androidx, my Koin test which injects repository to modify the response, the test failed, although it worked before. Now it creates wrong version of Repository and returns null to my flowable, more on this thing https://stackoverflow.com/questions/54040468/koin-testing-on-androidx-with-activity

To Reproduce
Steps to reproduce the behavior:

  1. copy the repository mentioned in the post
  2. run instrumented test
  3. see it fail

Expected behavior
The test should work, because prior to upgrade, everything worked fine and the test passed

Koin project used and used version (please complete the following information):
1.0.2

Additional moduleDefinition
none

koin-test accepted issue

Most helpful comment

stubbing function should be done on definition function, not just on the last returned instance.
right :)

All 3 comments

I went ahead and took a look at this. From what I can see, the issue resides in the fact that declareMock() isn't functioning as you would expect for a factory definition.

If you follow the source of declareMock() to declareMockedDefinition(), you'll see that it searches for the dependency definition, creates a copy, and then overrides it with a Mockito mock. However, in your case, your BuffarooRepository is a factory so each time a dependent accesses it from the Koin graph, it will receive a brand new mock. So the instance you access in your BrowseActivityTest via by inject() is different than the one that's accessed in the GetBufferoos class during the test. Only the instance in BrowseActivityTest has the mocked method; the instance in GetBufferoos class during the test is a fresh mock and has no mocked definitions and that's why it's returning null.

As for the workaround, you would need to change the BufferooRepository definition to be a single instead of a factory. However, that would mean that declareMock() doesn't work with factory and I would think that's a bug in Koin, but I'm not a project contributor.

The declareMock() method accepts a stubbing lambda with the definition (T.() -> Unit) such that you can setup your mock in this lambda. The bug is that this lambda is not invoked within the definition, it's only applied to the mock that's returned from declareMock(). The stubbing parameter needs to be passed down to declareMockedDefinition() and applied within definition so that it's invoked each time the definition is accessed – such as when the definition is a factory.

P.S: Even after applying the workaround stated above, the tests still fail during the teardown of the BrowseActivity. This is because your cleanUp() method in BrowseActivityTest is closing the Koin scope and the BrowseActivity attempts to also close the Koin scope via the bindScope call in its onCreate(). In short, I don't believe cleanUp() is necessary because the BrowseActivity will close its own Koin scope.

stubbing function should be done on definition function, not just on the last returned instance.
right :)

fixed in 2.0.0-beta2

Was this page helpful?
0 / 5 - 0 ratings

Related issues

miladsalimiiii picture miladsalimiiii  Â·  3Comments

mubarak1361 picture mubarak1361  Â·  3Comments

leodeleon22 picture leodeleon22  Â·  4Comments

hkelidari picture hkelidari  Â·  3Comments

AHarazim picture AHarazim  Â·  3Comments