简体   繁体   中英

@MockK or mockk()

When using the Mockk for Android Unit tests, there is any difference of using the notation when declaring dependencies?

class Test {
    private val x: X = mockk()

    private val test = TestClass(x)
...
}

or

class Test {
    @MockK
    private lateinit var x: X

    @InjectMockKs
    private lateinit var test: TestClass
    
    @Before
    fun setup() {
        MockKAnnotations.init(this)
    }
...
}

I'd recommend using mockk() and "naive" constructor dependencies injection in tests rather than annotations because of these two reasons:

  1. The mockk() builder allows you to define immutable variables with val which is more safe, efficient & better* (in terms of software development at all), whereas with @Mockk you should use var keyword;

  2. @InjectMockKs is not that cool as it seems. I worked on a project where I caught the same issue that Mockito has. My teammate removed one of the class dependencies somewhere in a middle of the constuctor arguments, built & ran the code, but forgot to fix & run tests locally. He pushed those changes, but then we got an error in our "Run Tests" pipeline stage which was pointed to nowhere, just NPE about missing class. We spent some extra time to finally find the issue, the thing is

Mockito will try to inject mocks only either by constructor injection, property injection or setter injection in order and as described below. If any of the following strategy fail, then Mockito won't report failure ; ie you will have to provide dependencies yourself.

https://www.javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/InjectMocks.html

From MockK project

No there is no difference between the two implementations, they are equivalent.

Generally speaking, you can use mockk() when you need to declare mocks dynamically in your code, or if you need, for instance, just a single mock to have its unit functions relaxed (in which case you would build it with mockk(relaxUnitFun = true).

If your mocks have all the same behavior, you can use the annotations version.

If your TestClass's dependency gonna change, using Annotation is better.

Because you just need to add/delete one more @MockK , don't need to care about the target class's constructor.

Original

@ExtendWith(MockKExtension::class)
class Test {
    @MockK
    private lateinit var x: X

    @InjectMockKs
    private lateinit var test: TestClass
}

Add one dependency for TestClass

@ExtendWith(MockKExtension::class)
class Test {
    @MockK
    private lateinit var x: X

    @MockK
    private lateinit var y: Y  // <1> Just add this

    @InjectMockKs
    private lateinit var test: TestClass  // <2> Don't need to add the changed dependency into it's constructor
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM