1

Hi i am new in Mockk library Kotlin. I want to mock view binding in unit testing. But i am unable to get proper example. I search Possible to mock/test Android ViewBinding interactions? I don't want to use @RunWith(PowerMockRunner::class). Does any one have better solution for this.

After @Eddie reply i tried my basic code.

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        setText()
    }

    internal fun setText() {
        binding.test.text = "shh"
    }
}

Test class

class MainActivityTest {

    @get:Rule
    val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()

    private lateinit var mainActivity: MainActivity

    @MockK
    private lateinit var mainBinding: ActivityMainBinding

    @Before
    fun setUp() {
        MockKAnnotations.init(this, relaxed = true)
        mockkStatic(ActivityMainBinding::class)
        mainActivity = spyk(MainActivity())
    }

    @Test
    fun `setupText - set text`() {
        verify { mainBinding.test.text = "2" }
        mainActivity.setText()
    }
}

I am getting this error

java.lang.NullPointerException
    at com.example.test.MainActivityTest$setupText - set text$1.invoke(MainActivityTest.kt:34)
    at com.example.test.MainActivityTest$setupText - set text$1.invoke(MainActivityTest.kt:34)
    at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:24)
    at io.mockk.impl.eval.RecordedBlockEvaluator$enhanceWithRethrow$1.invoke(RecordedBlockEvaluator.kt:74)
    at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
    at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:36)
    at io.mockk.impl.eval.VerifyBlockEvaluator.verify(VerifyBlockEvaluator.kt:30)
    at io.mockk.MockKDsl.internalVerify(API.kt:118)
    at io.mockk.MockKKt.verify(MockK.kt:149)
    at io.mockk.MockKKt.verify$default(MockK.kt:146)
    at com.example.test.MainActivityTest.setupText - set text(MainActivityTest.kt:34)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Kotlin Learner
  • 3,995
  • 6
  • 47
  • 127
  • What have you tried so far? How does your test looks like? Where are you stuck? Share some code to get better answers. – Eddie Lopez Jun 17 '21 at 16:58
  • Hey @Eddie i don't know where to start. My question is that how can mock view binding is there any other example without using powerMockRunner – Kotlin Learner Jun 17 '21 at 22:49
  • You can just mock static classes and objects with Mockk. From the top of my head, you would need to `mockkStatic(MyViewBinding::class)` or `mockkObject(MyViewBinding)`, assuming your layout is called `my_view.xml`, for example. I'm not sure what are they generating this days, statics or objects. Then you can make such mocks return the mocked view you need by using the `every {...}` DSL. – Eddie Lopez Jun 18 '21 at 15:41
  • Hi @EddieLopez I tried your solution, but i fail. Can you please tell me what i doing wrong in here – Kotlin Learner Jun 19 '21 at 20:45
  • @EddieLopez How to test text is setting in text view – Kotlin Learner Jun 19 '21 at 20:46
  • You have to set your `mainBinding` field to the mocked `ActivityMainBinding`, otherwise the binding will be null. So you don't need the static mocking, just make the field package private so you can assign it from the test. Annotate it as `@VisibleForTesting` so you know is only visible for tests. – Eddie Lopez Jun 21 '21 at 15:42
  • 1
    Hi @EddieLopez can you please give the example i didn't get it – Kotlin Learner Jun 22 '21 at 22:09
  • Hi @EddieLopez Can you share a sample. I am facing same issue while using Mockito with roboelectric to check a text in edittext. – Ankush Dec 11 '22 at 06:58

0 Answers0