lateinit 属性 apiInterface 尚未初始化 kotlin.UninitializedPropertyAccessException:?

lateinit property apiInterface has not been initialized kotlin.UninitializedPropertyAccessException:?

我正在为我的视图模型编写单元测试,当我 运行 测试时出现以下异常

lateinit property apiInterface has not been initialized
kotlin.UninitializedPropertyAccessException: lateinit property apiInterface has not been initialized
    at com.yodgorbek.newstask.presentation.viewmodel.BBCNewsViewModelTest.setUp(BBCNewsViewModelTest.kt:30)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.junit.runners.model.FrameworkMethod.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.RunBefores.invokeMethod(RunBefores.java:33)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
    at org.junit.rules.TestWatcher.evaluate(TestWatcher.java:61)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner.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.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access0(ParentRunner.java:66)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
    at org.gradle.api.interna

低于我的 BBCNewsViewModelTest.kt 我遇到异常的地方

@ExperimentalCoroutinesApi
class BBCNewsViewModelTest{
    private var progressObserver = MutableLiveData(false)
    private lateinit var apiInterface : NewsInterface

    private lateinit var newsRepository: NewsRepository
    private lateinit var bbcNewsResponseUseCase: BBCNewsResponseUseCase
    private lateinit var viewModel: BBCNewsViewModel
    @ExperimentalCoroutinesApi
    @get:Rule
    var mainCoroutineRule = MainCoroutineRule()

    @Before
    fun setUp() {
        newsRepository = NewsRepository(apiInterface)
        bbcNewsResponseUseCase = BBCNewsResponseUseCase(newsRepository)
        viewModel = BBCNewsViewModel(bbcNewsResponseUseCase)
    }

    @Test
    fun testsSaveSessionData() = runBlockingTest {
        assert(progressObserver.value == viewModel.progress.value)

    }

}

在我调用获取新闻功能的界面 class 下方

interface NewsInterface {

    @GET(Constants.BBC_URL)
    suspend fun getNews(): NewsResponse


}

低于BBCNewsViewModel.kt

  import android.os.Build
    import androidx.annotation.RequiresApi
    import androidx.lifecycle.MutableLiveData
    import androidx.lifecycle.ViewModel
    import androidx.lifecycle.viewModelScope
    import com.yodgorbek.newstask.model.NewsResponse
    import com.yodgorbek.newstask.domain.use_case.BBCNewsResponseUseCase
    import com.yodgorbek.newstask.domain.utils.fold
    import com.yodgorbek.newstask.domain.utils.parseDate
    
    import kotlinx.coroutines.Dispatchers
    import kotlinx.coroutines.launch
    import java.util.Comparator
    
        @RequiresApi(Build.VERSION_CODES.N)
        class BBCNewsViewModel(private val useCase: BBCNewsResponseUseCase) : ViewModel() {
        
        
             var news= MutableLiveData<NewsResponse>()
            // Expose to the outside world
        
            // Expose to the outside world
            private val error = MutableLiveData<String>()
            var progress = MutableLiveData(false)
        
        init{
            getNews()
        }
        
            @RequiresApi(Build.VERSION_CODES.N)
            private fun getNews() {
                progress.postValue(true)
                viewModelScope.launch(Dispatchers.IO) {
                    useCase.invoke()
                        .fold({ newsResponse ->
                            newsResponse.articles.sortedWith(Comparator.comparing{
                                it.publishedAt.parseDate()
                            })
                            news.postValue(newsResponse)
        
                        }, {
                            error.postValue(it.message)
                        })
                    progress.postValue(false)
                }
            }
        
        
        
        
        }

低于我的NewsRepository.kt

class NewsRepository(
   private val apiInterface:NewsInterface
){


@RequiresApi(Build.VERSION_CODES.N)
suspend fun getNews() : Result<NewsResponse>{
   return try {
       val response = apiInterface.getNews()
      Result.Success(response)
   } catch (ex: Exception) {
      Result.Error(ex)
   }
}



}

低于我的NewsResponse.kt

data class NewsResponse(
    @SerializedName("articles")
    val articles: List<Article>,
    @SerializedName("status")
    val status: String,
    @SerializedName("totalResults")
    val totalResults: Int
)

我想知道我到底哪里出错了

正如您的例外所述lateinit property apiInterface has not been initialized

BBCNewsViewModelTest中的apiInterface未初始化

并且在您的 setUp() 方法中,您正在初始化 newsRepository = NewsRepository(apiInterface)apiInterface 尚未初始化

您可以在声明时初始化您的 apiInterface,而无需 lateinit,或者在 setup() 中,或者如果您使用任何依赖注入,您可以进行字段注入

因为你正在使用改造,所以你必须这样初始化

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

NewsInterface service = retrofit.create(NewsInterface.class);

根据异常,您没有初始化 apiInterface

正常情况下Retrofit负责创建NewsInterface的实例。但是在测试的情况下,您将负责通过实例。为此,您可以创建模拟实现。

class MockNewsInterface: NewsInterface{
  suspend fun getNews(): NewsResponse{
     return NewsResponse() // Pass dummy implementation 
  }
}

只需在您的代码中替换它

newsRepository = NewsRepository(MockNewsInterface())

我建议使用 Mockito 或 Mockk.io 库。这将有助于轻松高效地编写测试用例。