检查是否未调用方法

时间:2012-10-21 21:09:37

标签: java jmockit

我想检查某个方法是否未运行并尝试使用期望设置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; }替换代码,测试也会通过:我必须遗漏一些明显的东西......

5 个答案:

答案 0 :(得分:8)

出现意外模拟行为的原因是您无意中在严格模拟的类型上使用了部分模拟。在这种情况下,使用times = <n>记录期望意味着将模拟第一个n匹配的调用,之后任何其他调用将执行原始的“unmocked”方法。使用常规模拟,您将获得预期的行为(即在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; }};
}

答案 1 :(得分:1)

与此相关我遇到了JMockit,times = 0和@Tested注释的问题。

使用@Tested注释,你仍然拥有一个真正的&#39; class,所以当在这个真正的类上注册Expectation或Verification(甚至是times = 0)时,JMockit会尝试执行该方法。解决方案是在Expectations中部分模拟类:

@Tested
Session s;

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

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

答案 2 :(得分: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();
}

答案 3 :(得分:0)

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

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

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

  new Verifications(){
    {
       Session.stop();
       maxTimes = 0;
    }
  };
}

答案 4 :(得分:-1)

从记忆中,像是

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

会奏效。麻烦的是,Session中的Whatever不是您的@Mock',而是另一个对象,因此请插入

w.s = s;

w.method()之前。

干杯,