简体   繁体   中英

mockk not working while executing entire android test package

I have written test cases for my view model. Which when I run individually or when I run the Test class . They get executed successfully . But when I run the complete androidTest package, I get this Exception io.mockk.MockKException

Here is the code that runs successfully in isolation.

@RunWith(AndroidJUnit4::class)
class MyViewModelTest{

    @Test
    fun test_one(){
        getInstrumentation().runOnMainSync(Runnable {
            val context = ApplicationProvider.getApplicationContext<Context>()
            mockkStatic(MyManager::class)
            val myInterface = mockk<MyInterface>()
            every { MyManager.getCommunicator() } returns myInterface
            every { myInterface.context } returns context
            every { myInterface.getLongFromGTM(any()) } returns 0
            val viewModel = MyViewModel(context as Application)
            viewModel.model = MyDataModel()
            viewModel.model.isRepeatEligible = true
            val res = viewModel.isRepeatEligible()
            Truth.assertThat(res).isTrue()
        })
    }

}

This is the error I am getting while running entire androidTest package:

在此处输入图像描述

Here are the detailed used classes

1.) MyManager.java

public class MyManager {
    private static MyInterface myCommunicator;
    
    public static MyInterface getCommunicator() {
        if (myCommunicator == null) {
            synchronized (MyManager.class) {
                if (myCommunicator == null) {
                    Class<?> cls = Class.forName("mypackage.communicator.MyCommunicator");
                    myCommunicator = (MyInterface) cls.newInstance();
                }
            }
        }
        return myCommunicator;
    }    
}

2.) MyViewModel.kt

class MyViewModel(application: Application) : BaseViewModel(application) {
    var model = MyDataModel()    
    private val timerDelay: Long by lazy {
        myCommunicator.getLongFromGTM("key_p2m_timer_delay")
    }
    val timerDuration: Long by lazy {
        myCommunicator.getLongFromGTM("key_p2m_timer_duration")
    }

    fun isRepeatEligible(): Boolean {
        model.apply {
            return isRepeatEligible && !isLinkBased && !isAlreadyPresent
        }
}

Mocking something with MockK is not contrained to just one function. Specifically, when you mock an object with mockkStatic , the object will from then on be a mock until it is unmocked using unmockkStatic or unmockkAll .

In your case, I guess the problem arises due to the static mocking of MyManager that lets subsequent tests fail, because they do not expect the object to be mocked.

This could be solved with an "after" function (eg using JUnit4, a function annotated with @After ) that calls unmockAll .

Alternatively, if you want to make sure that the object is only mocked locally, you can use a variant of mockkStatic that accepts a block that is the only place where the object is mocked like this:

mockkStatic(MyManager::class) {
   // inside this block, MyManager is mocked
}
// MyManager is automatically unmocked after the block
Update

As mentioned in your comment, you do not call MyManager.getCommunicator() directly in MyViewModel , but via an extension property

val myCommunicator : MyInterface = MyManager.getCommunicator()

This may cause your test setup to be still in place after your test, even when you unmock MyManager , because the property myCommunicator will keep its value - the mocked interface.

This can be solved by changing your property to not be initialized with the value of MyManager.getCommunicator() , but instead you should define a getter that calls MyManager.getCommunicator() :

val myCommunicator: MyInterface get() = MyManager.getCommunicator()

This way, you do always get the current value of MyManager.getCommunicator() and not the value that was set once on initialization.

Seehttps://kotlinlang.org/docs/properties.html#getters-and-setters for details on property getters.

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