我有一些正在测试的代码,它调用Java记录器来报告其状态。
在JUnit测试代码中,我想验证在这个日志记录器中创建了正确的日志条目。大致如下:
methodUnderTest(bool x){
if(x)
logger.info("x happened")
}
@Test tester(){
// perhaps setup a logger first.
methodUnderTest(true);
assertXXXXXX(loggedLevel(),Level.INFO);
}
我认为这可以用一个经过特别调整的记录器(或处理程序或格式化程序)来完成,但我更愿意重用现有的解决方案。(而且,老实说,我不清楚如何从记录器获得logRecord,但假设这是可能的。)
哇。我不知道为什么这么难。我发现我无法使用上面的任何代码示例,因为我使用的是log4j2而不是slf4j。这是我的解决方案:
public class SpecialLogServiceTest {
@Mock
private Appender appender;
@Captor
private ArgumentCaptor<LogEvent> captor;
@InjectMocks
private SpecialLogService specialLogService;
private LoggerConfig loggerConfig;
@Before
public void setUp() {
// prepare the appender so Log4j likes it
when(appender.getName()).thenReturn("MockAppender");
when(appender.isStarted()).thenReturn(true);
when(appender.isStopped()).thenReturn(false);
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
loggerConfig = config.getLoggerConfig("org.example.SpecialLogService");
loggerConfig.addAppender(appender, AuditLogCRUDService.LEVEL_AUDIT, null);
}
@After
public void tearDown() {
loggerConfig.removeAppender("MockAppender");
}
@Test
public void writeLog_shouldCreateCorrectLogMessage() throws Exception {
SpecialLog specialLog = new SpecialLogBuilder().build();
String expectedLog = "this is my log message";
specialLogService.writeLog(specialLog);
verify(appender).append(captor.capture());
assertThat(captor.getAllValues().size(), is(1));
assertThat(captor.getAllValues().get(0).getMessage().toString(), is(expectedLog));
}
}
通过添加Appender进行单元测试并不能真正测试Logger的配置。因此,我认为这是一种独特的情况,在这种情况下,单元测试没有带来那么多价值,而集成测试带来了很多价值(特别是如果您的日志有一些审计目的)。
为了为它创建集成测试,让我们假设您正在运行一个简单的ConsoleAppender,并希望测试它的输出。然后,您应该测试如何将消息从System.out写入到它自己的ByteArrayOutputStream。
从这个意义上说,我会做以下事情(我使用JUnit 5):
public class Slf4jAuditLoggerTest {
private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
@BeforeEach
public void beforeEach() {
System.setOut(new PrintStream(outContent));
}
通过这种方式,你可以简单地测试它的输出:
@Test
public void myTest() {
// Given...
// When...
// Then
assertTrue(outContent.toString().contains("[INFO] My formatted string from Logger"));
}
如果你这样做了,你将为你的项目带来更多的价值,而不需要使用内存中的实现,创建一个新的Appender,或者其他什么。