当前位置: 首页 > 知识库问答 >
问题:

机械分子Mockito——“需要但未调用”

穆建元
2023-03-14

我试图学习RobolectraMockito,以实现我正在为一个已经工作的Android项目创建测试。但是我有一些麻烦。这会让你知道我想测试的活动:

public class MainActivity extends FragmentActivity {

    public Session session;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        session = getActiveSession();
        if (session == null ) {
            // ...
        } else {
            if (sessionClosed()) {
                LoginFragment fragment = new LoginFragment();
                FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                ft.replace(R.id.container, fragment);
                ft.commit();
            }
        }
    }

    ...

    public Session getActiveSession() {
        return Session.getActiveSession();
    }

    public boolean sessionClosed() {
        return session.isClosed();
    }

}

这段代码所做的是获取ActiveFacebook会话,根据它的状态,它显示了不同的片段。现在我将向您展示测试类:

@RunWith(RobolectricTestRunner.class)
public class MainActivityTest {

    private ActivityController<?> controller;
    private MainActivity activity;
    private MainActivity spy;

    @Before
    public void setup() throws Exception {
        controller = Robolectric.buildActivity(MainActivity.class);
        activity = (MainActivity) controller.create().get();
        spy = Mockito.spy(activity);
    }

    @Test
    public void testShowLoginWhenSessionClosed() {
        Session session = new Session(Robolectric.application);

        Mockito.doReturn(session).when(spy).getActiveSession();
        Mockito.doReturn(true).when(spy).sessionClosed();

        Mockito.verify(spy).getActiveSession();

        Fragment fragment = activity.getSupportFragmentManager()
                .findFragmentById(R.id.container);
        Assert.assertTrue(fragment instanceof LoginFragment);
    }

}

正如你所见,我在一个单独的java项目中使用了Robolectric和Mockito。当我运行测试类时,我得到以下信息:

Wanted but not invoked:
mainActivity.getActiveSession();
-> at org.example.MainActivityTest.testShowLoginWhenSessionClosed(MainActivityTest.java:101)
Actually, there were zero interactions with this mock.

at org.example.MainActivityTest.testShowLoginWhenSessionClosed(MainActivityTest.java:101)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:236)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:158)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

你能帮我一下吗?

编辑

我去掉了ActivityController,以查看手动处理生命周期是否有效,但我收到了相同的“想要但未调用”消息:

@Test
public void testShowLoginWhenSessionClosed() throws Exception {
    Session session = new Session(Robolectric.application);
    MainActivity myActivity = Mockito.mock(MainActivity.class);

    Mockito.when(myActivity.getActiveSession()).thenReturn(session);
    Mockito.when(myActivity.sessionClosed()).thenReturn(true);

    myActivity.onCreate(null);
    myActivity.getActiveSession(); // works only if i call it manually

    Mockito.verify(myActivity).getActiveSession();

    Fragment fragment = myActivity.getSupportFragmentManager()
            .findFragmentById(R.id.container);
    Assert.assertTrue(fragment instanceof LoginFragment);

}

然而这一次它说:

However, there were other interactions with this mock:

指向myActivity。onCreate(空)行。

编辑2

如果使用spy,并对spied活动调用onCreate(),如下所示:

private ActivityController<MainActivity> controller;
private MainActivity activity;
private MainActivity spy;

@Before
public void setup() throws Exception {
    controller = Robolectric.buildActivity(MainActivity.class);
    activity = (MainActivity) controller.get();
}

@Test
public void testShowLoginWhenSessionClosed() throws Exception {
    Session session = new Session(Robolectric.application);
    spy = Mockito.spy(activity);

    Mockito.doReturn(session).when(spy).getActiveSession();
    Mockito.doReturn(true).when(spy).sessionClosed();

    spy.onCreate(null);

    Mockito.verify(spy).getActiveSession();

    Fragment fragment = spy.getSupportFragmentManager().findFragmentById(R.id.container);
    Assert.assertTrue(fragment instanceof LoginFragment);

}

然后我得到以下异常,指向行spy。onCreate(空)

java.lang.IllegalStateException: System services not available to Activities before onCreate()
at android.app.Activity.getSystemService(Activity.java:4492)
at android.view.LayoutInflater.from(LayoutInflater.java:211)
at org.robolectric.shadows.ShadowActivity.getLayoutInflater(ShadowActivity.java:148)
at android.app.Activity.getLayoutInflater(Activity.java)
at org.example.MainActivityTest.testShowLoginWhenSessionClosed(MainActivityTest.java:109)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:236)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:158)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

共有1个答案

巴星华
2023-03-14

你的测试有很多问题。

  • 您正在创建一个间谍,但实际上并没有在测试中使用它

此外,堆栈跟踪与您展示的代码不匹配——您可能正在运行旧版本的源代码。你需要清理目标目录并重建。

 类似资料:
  • 我知道其他人问过这个(或类似的)问题,但没有一个解决方案对我有帮助。我有3节课: 我的测试类: 我想验证B. subMethod()是否在A. superMethod()中被调用。我如何才能完成此任务。我知道我需要使用PowerMock来完成此任务,但我不确定如何。此外,我不允许更改有关A类或B类的任何内容。 任何帮助都将不胜感激!

  • 我实际上是在努力做下面的事情:我的服务类 这让我想要的没有被调用,实际上与这个模拟没有任何交互。你知道我做错了什么吗??

  • 我正在做一个单元测试,在我的应用程序中的类,它只是一个简单的类,我认为我做的一切都是正确的,但测试失败了,说: 需要但未调用:MContextWeakReference.Get();->在rahmat.com.app.utility.backwardcompatibility.StringResourceUtilTest.GetString(StringResourceUtilTest.java:

  • 晚安, 我正在对我的服务进行一些测试,在删除方法中执行测试时遇到了问题。 我想知道是否有人犯过这个错误,可以帮助我。 我扫描时出错。据报道,该方法没有使用。 例外情况: 代码:

  • 我在试着重构一些声纳上的假设。在重构之前,代码如下所示: 所以我把这些方法添加到一个映射中,并像这样调用它 我没有修改测试类中的任何内容,但我得到了以下错误: 被通缉但未被援引: - 但是揭穿它,它实际上是有效的,断言是正确的。原因可能是什么?

  • 我有如下测试方法: 是我要模拟并返回空映射的方法。但我收到的失败信息说 需要但未调用MyClass.MethodUsedInMethodBeingTest() .