【发布时间】:2015-04-30 05:55:28
【问题描述】:
我对 jMockIt 框架比较陌生,几个月前我开始在一个个人项目中使用它,以便在我们的一个企业项目中进行调整。 到目前为止,它看起来很有希望,而且它看起来是我们目前使用的 Mockito + Powermock 组合的一个不错的选择。 不应阅读此声明,因为我不提倡简单,但也没有义务仅仅为了让事情更容易测试而妥协您的设计,这绝对是非常吸引人的。
在我看来,另一件吸引人的事情是 Strict Expectations 的可用性。我理解这个概念的方式是,如果我使用多个模拟的协作者来测试类,那么不设置与这些模拟的协作者的确切交互将导致测试失败。实际上,这似乎不会发生。在我看来,为了让被模拟的协作者监控其交互,您需要至少对被模拟的协作者设定一个期望。
当我意识到这一点时,我感到有点失望,因为在添加新的协作者时很容易导致代码未经测试。希望我的方法不是正确的,并且这里的某个人能够将我引向正确的方向。 我整理了一个简短的测试用例,以便更容易重现我所说的内容。
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");
}};
}
}
上述单元测试通过。如果您注释掉整个验证块或者如果您没有验证块并将记录器交互移动到期望块中,它也会通过。我的预期是,如果我有一个模拟记录器并且与该记录器有交互,那么缺少与该记录器相关的严格期望或验证条目将导致我的测试失败。
提前感谢您的澄清。
【问题讨论】:
-
您在寻找类似 Mockito 的
verifyNoMoreInteractions()的东西吗?无论如何,JMockit 不支持在创建时声明为严格的模拟对象;相反,它支持 turning 模拟类型或实例在其上记录StrictExpectation时进行严格控制,并验证所有调用是否通过FullVerifications明确说明。因此,您不能只声明一个模拟字段/参数而导致测试失败,而无需在其中为该模拟编写任何期望或验证。 -
谢谢罗杰里奥。如果您将其发布为答案,我很高兴接受您的评论。这不是我想听到的,但你说的看起来是正确的。但是我不知道这会有多难,但在我看来,能够在模拟类型声明中说这个模拟是严格的,而不是在第一个严格的期望时将它变成严格的,这将是一个非常好的特性记录反对它。只需向 Mocked 注释添加一个“严格”属性即可。
-
可以做到(添加
@Mocked(strict = true)属性),是的。但问题是严格的模拟在几年前已经变得“不受欢迎”(在 Java 和 .NET 领域)。对于 JMockit,可以选择在测试结束时进行验证,仅使用非严格的模拟。所以,今天,如果你想要严格的模拟,你将不得不使用 EasyMock 或 jMock;此时,最好将其保留在 JMockit 中。
标签: java unit-testing jmockit