5

我想检查一个方法是否没有运行并尝试使用 Expectation setting 来执行它times = 0;,但是我没有得到预期的行为。

比如下面的测试通过了,虽然Session#stop方法被调用了,并且期望有一个times = 0;条件:

public static class Session {
    public void stop() {}
}

public static class Whatever {
    Session s = new Session();
    public synchronized void method() {
        s.stop();
    }
}

@Test
public void testWhatever () throws Exception {
    new Expectations(Session.class) {
        @Mocked Session s;
        { s.stop(); times = 0; } //Session#stop must not be called
    };
    final Whatever w = new Whatever();
    w.method(); // this method calls Session#stop => the test should fail...
                // ... but it passes
}

注意:如果我用 替换代码{ s.stop(); times = 1; },测试也通过了:我必须在这里遗漏一些明显的东西......

4

5 回答 5

8

意外模拟行为的原因是您无意中对严格模拟的类型使用了部分模拟。在这种情况下,记录期望times = <n>意味着第一个n匹配的调用将被模拟,之后任何其他调用将执行原始的“未模拟”方法。相反,使用常规模拟,您将获得预期的行为(即,调用UnexpectedInvocation后抛出异常)。n

编写测试的正确方法是:

public static class Session { public void stop() {} }
public static class Whatever {
    Session s = new Session();
    public synchronized void method() { s.stop(); }
}

@Test
public void testWhatever ()
{
    new Expectations() {
        @Mocked Session s;
        { s.stop(); times = 0; }
    };

    final Whatever w = new Whatever();
    w.method();
}

或者,也可以使用验证块来编写,这通常更适合以下情况:

@Test
public void testWhatever (@Mocked final Session s)
{
    final Whatever w = new Whatever();
    w.method();

    new Verifications() {{ s.stop(); times = 0; }};
}
于 2012-10-23T10:58:46.707 回答
3

与此相关,我在使用 JMockit、times = 0 和 @Tested 注释时遇到了麻烦。

使用@Tested 注释,您仍然有一个“真实”类,因此当在这个真实类上注册期望或验证(即使时间 = 0)时,JMockit 会尝试执行该方法。解决方案是部分模拟期望中的类:

@Tested
Session s;

new Expectations(Session.class) {{ 
   s.stop(); times = 0; } //Session#stop must not be called
};

这是我发现在 @Tested 类的方法上使用 times=0 的唯一方法。

于 2015-12-07T15:00:24.517 回答
0

我找到了MockUp该类的解决方法 - 下面的测试按预期失败 -我仍然想了解为什么原来的方法不起作用

@Test
public void testWhatever () throws Exception {
    new MockUp<Session>() {
        @Mock
        public void stop() {
            fail("stop should not have been called");
        }
    };
    final Whatever w = new Whatever();
    w.method();
}
于 2012-10-21T22:24:33.083 回答
0

尝试使用 maxTimes ,您也可以以静态方式引用 stop() :

@Test
public void test(@Mocked Session mockSession){

  final Whatever w = new Whatever();
  w.method();

  new Verifications(){
    {
       Session.stop();
       maxTimes = 0;
    }
  };
}
于 2016-07-26T12:46:12.247 回答
-1

从记忆中,类似于

verify( s  , times(0) ).stop();

将工作。麻烦的是,SessioninWhatever不是你@Mock的,而是另一个对象,所以插入一个

w.s = s;

就在之前w.method()

干杯,

于 2012-10-21T21:25:00.070 回答