它试图执行应存根的功能

它试图执行应存根的功能

本文介绍了Mockito存根失败:它试图执行应存根的功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

存根是如何工作的?如果我理解正确,那么存根就是模拟功能的覆盖.因此,在存根时,mockito应该仅查看函数的签名,而不要尝试执行将存根的函数.

how does stubbing works exactly ? If I understood correctly, a stub is an overwrite of a function of a mock. So when stubbing, mockito should only look at the signature of the function, not try to execute the function that will be stubbed.

但是我的测试文件在存根时失败,原因是:它试图到达要在存根函数的原始代码中调用的模拟函数内部的空指针

But my test file fails when stubbing, the reason : it tries reach a null pointer inside the mocked function that is called in the original code of the to-be-stubbed function

是我理解错误的存根,还是Mockito未能按预期工作?

Is it me that understands stubbing incorrectly or is Mockito not working as intended ?

预先感谢您的帮助.

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context
android.content.Context.getApplicationContext()' on a null object reference
at com.micheladrien.fresquerappel.tools.JsonReader.loadJSONFromAsset(JsonReader.kt:50)
at com.micheladrien.fresquerappel.tools.JsonReader.readJsonObject(JsonReader.kt:17)
at com.micheladrien.android.fresquerappel.MainDataManagerTest.set_up(MainDataManagerTest.kt:24)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:54)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:99)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:105)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:40)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:395)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2081)

这是我的测试文件:

    package com.micheladrien.android.fresquerappel

    import com.micheladrien.fresquerappel.datas.RelationModel
    import com.micheladrien.fresquerappel.manager.MainDataManager
    import com.micheladrien.fresquerappel.tools.JsonReader
    import junit.framework.Assert.assertFalse
    import org.junit.Before
    import org.junit.Test
    import org.junit.runner.RunWith
    import org.mockito.Mock
    import org.mockito.Mockito.*
    import org.mockito.junit.MockitoJUnitRunner

    @RunWith(MockitoJUnitRunner::class)
    class MainDataManagerTest {


    @Mock
    val mockJsonReader: JsonReader = mock(JsonReader::class.java)

    @Before
    fun set_up() {
        //Line that doesn't work
        `when`(mockJsonReader.readJsonObject("test")).thenReturn(mutableListOf<RelationModel>())
    }

    //Nous verifions qu'à la base, les données ne sont pas marquées comme chargées.
    @Test
    fun testDataUnloaded(){
        val singletonDataManager:MainDataManager.SingletonDataManager = MainDataManager.SingletonDataManager(mockJsonReader)
        //Assert/AssertFalse : verifie que la valeur est vrai ou fausse.
        assertFalse(singletonDataManager.isDataInitialised())
    }
   }

更多:

    apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'

    android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.micheladrien.fresquerappel"
        minSdkVersion 22
        targetSdkVersion 29
        versionCode 12
        versionName "1.2"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    }

    dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.3'
    def navigation_version = '2.3.1'
    implementation "androidx.navigation:navigation-fragment-ktx:$navigation_version"
    implementation "androidx.navigation:navigation-ui-ktx:$navigation_version"
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation "androidx.navigation:navigation-fragment:$navigation_version"
    implementation "androidx.navigation:navigation-ui:$navigation_version"
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation 'androidx.annotation:annotation:1.1.0'
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    implementation 'il.co.theblitz:observablecollections:1.4.2'
    def espressocore_version = '3.3.0'
    androidTestImplementation "androidx.test.espresso:espresso-core:$espressocore_version"
    androidTestImplementation "androidx.test.espresso:espresso-core:$espressocore_version"
    androidTestImplementation "android.arch.core:core-testing:$lifecycle_version"
    def mockito_version = '3.5.5' // For local unit tests on your development machine
    testImplementation "org.mockito:mockito-core:$mockito_version" // For instrumentation tests on Android devices and emulators
    androidTestImplementation "org.mockito:mockito-android:$mockito_version"
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test:rules:1.0.2'
    androidTestImplementation 'com.android.support:support-annotations:24.0.0'
}

这是JsonReader:包com.micheladrien.fresquerappel.tools

Edit :Here is JsonReader :package com.micheladrien.fresquerappel.tools

import android.content.Context
import android.util.Log
import com.micheladrien.fresquerappel.datas.RelationModel
import org.json.JSONArray
import org.json.JSONException
import java.io.IOException
import java.io.InputStream


open class JsonReader(val context:Context) {

fun readJsonObject(file_name:String):MutableList<RelationModel>{

    try {
        val jArray = JSONArray(loadJSONFromAsset(file_name))
        //val jArray = JSONArray("[{\"c1\": 1,\"c2\": 2,\"rel\": \"UP\",\"mandatory\": \"mandatory\",\"expl\": \"\"}]")
        val list = mutableListOf<RelationModel>()

        for (i in 0 until jArray.length()) {

            val card1: String =
                jArray.getJSONObject(i).getString("c1")
            val card2: String =
                jArray.getJSONObject(i).getString("c2")
            val direction: String =
                jArray.getJSONObject(i).getString("rel")
            val mandatory:String =
                jArray.getJSONObject(i).getString("mandatory")
            val explanation: String =
                jArray.getJSONObject(i).getString("expl")

            val rel = RelationModel(card1, card2, direction, mandatory, explanation)

            list.add(rel)
        }

        return list
    } catch (e: JSONException) {
        e.printStackTrace()
        return mutableListOf<RelationModel>()
    }
}

private fun loadJSONFromAsset(file_name:String): String? {
    val low_file_name : String = file_name.toLowerCase()

    val json = try {
        val assetManager = context.applicationContext.assets
        val `is`: InputStream = assetManager.open("json/" + low_file_name + ".json")
        val size: Int = `is`.available()
        val buffer = ByteArray(size)
        `is`.read(buffer)
        `is`.close()
        //Nous renvoyons le string pour json
        String(buffer, Charsets.UTF_8)
    }catch (ex: IOException) {
        ex.printStackTrace()
        return null
    }
    return json

}


}

使loadJSONFromAsset失败的函数是私有的(应模拟的函数调用该函数).我把它公开了,但是有同样的错误.

The function that fails loadJSONFromAsset is private (it is the function that is called by the function that should be mocked). I put it public, but same error.

//Singleton : https://blog.mindorks.com/how-to-create-a-singleton-class-in-kotlin
package com.micheladrien.fresquerappel.manager

import android.content.Context
import android.util.Log
import com.micheladrien.fresquerappel.R
import com.micheladrien.fresquerappel.datas.Relation
import com.micheladrien.fresquerappel.datas.RelationDirection
import com.micheladrien.fresquerappel.datas.RelationMandatory
import com.micheladrien.fresquerappel.datas.RelationModel
import com.micheladrien.fresquerappel.fragment.single.Single
import com.micheladrien.fresquerappel.tools.JsonReader

class MainDataManager(context: Context) : DataManager {
val mainDataManager : SingletonDataManager = SingletonDataManager.getInstance(context)

init{
   if (!isDataInitialised()){
       loadData(context.getString(R.string.collage_climat))
   }

}

override fun isDataInitialised(): Boolean {
    return mainDataManager.isDataInitialised()
}

override fun loadData(file_name: String) {
    synchronized(mainDataManager){
        mainDataManager.loadData(file_name)
    }

}

override fun researchRelation(number1: Int, number2: Int): RelationModel {
    synchronized(mainDataManager) {
        return mainDataManager.researchRelation(number1, number2)
    }
}

override fun researchSingle(number1: Int): Single {
    synchronized(mainDataManager){
        return mainDataManager.researchSingle(number1)}
}



//Subclass. Cette classe ne sera instanciée qu'une fois
class SingletonDataManager(val jsonReader: JsonReader){

    companion object {
        lateinit private var instance : SingletonDataManager
        var boolInit:Boolean = false

        private fun isInitialised():Boolean{
            return boolInit
        }

        fun getInstance(context: Context): SingletonDataManager{
            if(isInitialised()) {
                return instance
            }
            else {
                val newJsonReader = JsonReader(context)
                instance = SingletonDataManager(newJsonReader)
                boolInit = true
                return instance
            }
        }
    }

    private var list: MutableList<RelationModel>? = null
    private var is_list_init:Boolean = false


    fun loadData(file_name : String){
        list = jsonReader.readJsonObject(file_name)
        Log.d("ami", "Nous avons init la bdd")
        is_list_init = true
    }

    fun isDataInitialised():Boolean{
        return this.is_list_init
    }

    fun researchRelation(number1:Int, number2:Int): RelationModel {
        list?.forEach {
            if(it.number1 == number1){
                if(it.number2 == number2)
                    return it
            }
        }
        return RelationModel(number1, number2,     Relation(RelationDirection.NONE, RelationMandatory.OPTIONAL) , "")
    }

    fun researchSingle(number1: Int): Single {
        TODO("Not yet implemented")
    }
}
}

推荐答案

正如弗雷德在上述评论中所说的:

As Fred said in the comment above :

此问题已解决.

这篇关于Mockito存根失败:它试图执行应存根的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 21:06