![](/img/trans.png)
[英]declareMock<> not working with mockk in android unit test
[英]Koin test declareMock not working with multiples declaration
我试图声明两个模拟,但我得到一个 java.lang.ClassCastException。
我正在尝试测试我的 MainActivity(它有一个 MainViewModel),所以我需要模拟 MainViewModel。 问题是当我启动 MainActivity 进行测试时,SplashFragment 被注入,因为我正在使用导航组件并且我的 MainActivity 包含一个 NavHostFragment 并且默认情况下启动 SplashFragment(它有一个 SplashViewModel)。
总结:App -> MainActivity(尝试测试MainActivity中的一些常用组件) -> Splash Fragment
private val testViewState = MediatorLiveData<MainViewState>()
private val testSplashViewState = MediatorLiveData<SplashViewState>()
@Rule
@JvmField
var mockSplashViewModelRule = MockProviderRule.create {
mock(SplashViewModel::class.java)
}
@Rule
@JvmField
var mockViewModelRule = MockProviderRule.create {
mock(MainViewModel::class.java)
}
private fun launchMainActivity() {
declareMock<SplashViewModel> {
given(viewState).willReturn(testSplashViewState)
}
declareMock<MainViewModel> {
given(viewState).willReturn(testViewState)
}
activityScenarioRule.scenario
}
我收到此错误: java.lang.ClassCastException:SplashViewModel 无法转换为 MainViewModel
如果我没有声明我得到的SplashViewModel:java.lang.RuntimeException:org.koin.core.error.NoBeanDefFoundException:没有找到 class 的定义:'SplashViewModel'。 检查你的定义!
有任何想法吗?
我是这样解决的:
private val testSplashViewState = MediatorLiveData<SplashViewState>()
private val testViewState = MediatorLiveData<MainViewState>()
@Mock
private lateinit var mainViewModel: MainViewModel
@Mock
private lateinit var splashViewModel: SplashViewModel
@Rule
@JvmField
var activityScenarioRule = LateInitActivityScenarioRule(MainActivity::class.java, false)
val module = module(createdAtStart = true, override = true) {
viewModel { splashViewModel }
viewModel { mainViewModel }
}
@Before
fun setupMainActivityTest() {
loadKoinModules(module)
}
@After
fun afterMainActivityTest() {
unloadKoinModules(module)
}
private fun launchMainActivity() {
testSplashViewState.value = SplashViewState()
whenever(splashViewModel.viewState).thenReturn(testSplashViewState)
testViewState.value = MainViewState()
whenever(mainViewModel.viewState).thenReturn(testViewState)
activityScenarioRule.scenario
}
/**
* Copyright 2018 The Android Open Source Project
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import android.app.Activity;
import android.content.Intent;
import androidx.annotation.Nullable;
import androidx.test.core.app.ActivityScenario;
import org.junit.rules.ExternalResource;
import static androidx.test.internal.util.Checks.checkNotNull;
/**
* PrincipalActivityScenarioRule launches a given activity before the test starts and closes after the test.
*
* <p>You can access to scenario interface via {@link #getScenario()} method. You may finish your
* activity manually in your test, it will not cause any problems and this rule does nothing after
* the test in such cases.
*
* <p>This rule is an upgraded version of {@link androidx.test.rule.ActivityTestRule}. The previous
* version will be deprecated and eventually be removed from the library in the future.
*
* <pre>{@code
* Example:
* }{@literal @Rule}{@code
* PrincipalActivityScenarioRule<MyActivity> rule = new PrincipalActivityScenarioRule<>(MyActivity.class);
*
* }{@literal @Test}{@code
* public void myTest() {
* ActivityScenario<MyActivity> scenario = rule.getScenario();
* // Your test code goes here.
* }
* }</pre>
*/
public final class LateInitActivityScenarioRule<A extends Activity> extends ExternalResource {
/**
* Same as {@see java.util.function.Supplier} which requires API level 24.
*
* @hide
*/
interface Supplier<T> {
T get();
}
private Supplier<ActivityScenario<A>> scenarioSupplier;
@Nullable
private ActivityScenario<A> scenario;
private boolean initOnBefore;
/**
* Constructs PrincipalActivityScenarioRule for a given activity class.
*
* @param activityClass an activity class to launch
*/
public LateInitActivityScenarioRule(Class<A> activityClass, boolean initOnBefore) {
this.initOnBefore = initOnBefore;
scenarioSupplier = () -> ActivityScenario.launch(checkNotNull(activityClass));
}
/**
* Constructs PrincipalActivityScenarioRule for a given activity class and intent.
*
* @param startActivityIntent an intent to start the activity
*/
public LateInitActivityScenarioRule(Intent startActivityIntent, boolean initOnBefore) {
this.initOnBefore = initOnBefore;
scenarioSupplier = () -> ActivityScenario.launch(checkNotNull(startActivityIntent));
}
@Override
protected void before() throws Throwable {
if (initOnBefore) {
ensureScenario();
}
}
@Override
protected void after() {
if (scenario != null) {
scenario.close();
}
}
/**
* Returns {@link ActivityScenario} of the given activity class.
*
* @return a non-null {@link ActivityScenario} instance
* @throws {@see NullPointerException} if you call this method while test is not running
*/
public ActivityScenario<A> getScenario() {
ensureScenario();
return checkNotNull(scenario);
}
/**
* Returns {@link ActivityScenario} of the given activity class.
*
* @return a non-null {@link ActivityScenario} instance
* @throws {@see NullPointerException} if you call this method while test is not running
*/
public ActivityScenario<A> createScenario(Intent intent) {
scenarioSupplier = () -> ActivityScenario.launch(checkNotNull(intent));
ensureScenario();
return checkNotNull(scenario);
}
private void ensureScenario() {
if (scenario == null) {
scenario = scenarioSupplier.get();
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.