jMockIt StrictExpectations 如何工作

how jMockIt StrictExpectations work

我对 jMockIt 框架比较陌生,几个月前我开始在一个个人项目中使用它,目的是在我们的一个企业项目中对其进行调整。 到目前为止,它看起来很有前途,它看起来是我们目前已有的 Mockito + Powermock 组合的一个很好的替代品。 不应阅读此声明,因为我不是在提倡简单性,而是没有义务为了让事情更容易测试而妥协您的设计,这绝对非常有吸引力。

在我看来,另一件吸引人的事情是严格期望的可用性。我理解这个概念的方式是,如果我使用多个模拟协作者对 class 进行测试,那么不设置与这些模拟协作者的确切交互将导致测试失败。实际上这似乎并没有发生。在我看来,为了让模拟协作者的交互受到监控,您至少需要针对该模拟协作者设置一个期望值。

当我意识到这一点时,我感到有点失望,因为在添加新协作者时它很容易导致未经测试的代码。希望我的方法不是正确的,并且这里的某个人能够让我走上正确的方向。 我整理了一个简短的测试用例,以便更容易重现我所说的内容。

package my.testing.pkg;

import mockit.Mocked;
import mockit.StrictExpectations;
import mockit.Verifications;
import mockit.integration.junit4.JMockit;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;

@RunWith(JMockit.class)
public class LoggerTest {
    class ClassUnderTest {
        private final Logger logger = Logger.getLogger(ClassUnderTest.class);
        String getString() {
            logger.debug("about to return a string");
            return "xyz";
        }
    }

    @Mocked
    private Logger logger;

    @Test
    public void shouldReturnTheRightString() throws Exception {
        new StrictExpectations() {{
        }};
        assertEquals("xyz", new ClassUnderTest().getString());
        new Verifications() {{
            logger.debug("about to return a string");
        }};
    }
}

以上单元测试通过。如果您注释掉整个验证块,或者如果您没有验证块并将记录器交互移动到期望块中,它也会通过。我期望的是,如果我有一个模拟记录器并且与该记录器有交互,那么缺少与该记录器相关的严格期望或验证条目将导致我的测试失败。

提前感谢您的澄清。

JMockit 不支持在创建时声明为严格的模拟对象;相反,如果在其上记录了 StrictExpectation,它支持将模拟类型或实例转换为严格,并验证是否通过 FullVerifications 明确说明了所有调用。因此,您不能只声明一个模拟 field/parameter 并让测试失败而不为该模拟编写任何期望或验证。

虽然 @Mocked(strictly = true) 属性 可以 添加到 API,但严格的模拟已经成为 "unpopular" 年前(在 Java 和 .NET 领域)。对于 JMockit,可以选择在测试结束时进行验证,仅使用非严格模拟。所以,今天,如果你想要严格的模拟,你将不得不使用 EasyMock 或 jMock;此时,最好将其保留在 JMockit 中。