我有一个SLF4J记录器实例的类,如:
public class MyClass {
private static final Logger log = LoggerFactory.getLogger(MyClass.class);
public void foo() {
log.warn("My warn");
}
}
我需要用JMockit测试它,如:
@Test
public void shouldLogWarn(@Mocked Logger log) throws Exception {
new Expectations() {{
log.warn(anyString);
}};
MyClass my = new MyClass();
my.foo();
}
经过大量搜索后我发现,我需要以某种方式使用MockUp。但无法准确地了解它。
顺便说一句,我使用的是最后一个版本的JMockit(1.29),你不能再 setField(log)来获得最终的静态字段。
答案 0 :(得分:6)
@Capturing
注释表示模拟字段或模拟参数,扩展/实现模拟类型的所有类也将被模拟。
捕获模拟类型的未来实例(即,在测试期间稍后创建的实例)将与模拟字段/参数相关联。在模拟字段/参数上记录或验证期望时,这些关联的实例被视为等效于为模拟字段/参数创建的原始模拟实例。
这意味着如果您使用@Capturing
而不是@Mocked
对其进行注释,则在测试运行期间创建的每个Logger
都将与您注释的相关联。以下是有效的:
@Test
public void shouldLogWarn(@Capturing final Logger logger) throws Exception {
// This really ought to be a Verifications block instead
new Expectations() {{
logger.warn(anyString);
}};
MyClass my = new MyClass();
my.foo();
}
作为旁注,如果您要做的只是验证方法是否被调用,那么最好使用Verifications,因为这是它的目的。所以你的代码看起来像这样:
@Test
public void shouldLogWarn(@Capturing final Logger logger) throws Exception {
MyClass my = new MyClass();
my.foo();
new Verifications() {{
logger.warn(anyString);
}};
}
@Mocked
和Logger
LoggerFactory
在某些情况下,由于注释工作原理的复杂性,@Capturing
无法按预期工作。幸运的是,您可以使用@Mocked
和Logger
LoggerFactory
来获得相同的效果,如下所示:
@Test
public void shouldLogWarn(@Mocked final LoggerFactory loggerFactory, @Mocked final Logger logger) throws Exception {
MyClass my = new MyClass();
my.foo();
new Verifications() {{
logger.warn(anyString);
}};
}
注意: JMockit 1.34到1.38 has a bug会阻止它使用slf4j-log4j12
,以及可能还有SLF4J的其他依赖项。如果您遇到此错误,请升级到1.39或更高版本。