{{announcement.body}}
{{announcement.title}}

Unit Testing Log Messages Made Easy

DZone 's Guide to

Unit Testing Log Messages Made Easy

Even I faced difficulty with unit testing, and so I wanted to make it easier for myself and share it with you! — LogCaptor library came into life.

· Performance Zone ·
Free Resource

As a Java Developer, we need to cover a lot of scenarios to ensure the quality of our software and catch bugs as soon as possible when introducing a new code. For 99% of all my use cases AssertJ, Junit, Mockito, and Wiremock are sufficient enough do cover the test cases. But for the other use cases, like unit testing info, debug or warn log messages, these frameworks don't help you out. There is also no other framework that can provide an easy to use method to capture log messages.

The answer which the community provided works well, but it is a lot of boilerplate code to just assert your log events. Even I faced the same trouble and so I wanted to make it easier for myself and share it with you! So the LogCaptor library came into life.

You may also like: The Complete Unit Testing Collection [Tutorials and Frameworks]

Include the following dependency in your project as a test dependency:

Java
 




x


 
1
<dependency>
2
    <groupId>io.github.hakky54</groupId>
3
    <artifactId>logcaptor</artifactId>
4
    <version>1.0.1</version>
5
    <scope>test</scope>
6
</dependency>



Let's assume you have the following service which creates logs:

Java
 




xxxxxxxxxx
1
13


 
1
import org.apache.logging.log4j.LogManager;
2
import org.apache.logging.log4j.Logger;
3
 
          
4
public class FooService {
5
 
          
6
    private static final Logger LOGGER = LogManager.getLogger(FooService.class);
7
 
          
8
    public void sayHello() {
9
        LOGGER.info("Keyboard not responding. Press any key to continue...");
10
        LOGGER.warn("Congratulations, you are pregnant!");
11
    }
12
 
          
13
}



And let's create a unit test for this service to assert the log messages and even the log levels

Java
 




xxxxxxxxxx
1
19


 
1
import static org.assertj.core.api.Assertions.assertThat;
2
import org.junit.Test;
3
 
          
4
public class FooServiceShould {
5
 
          
6
    @Test
7
    public void logInfoAndWarnMessages() {
8
        String expectedInfoMessage = "Keyboard not responding. Press any key to continue...";
9
        String expectedWarnMessage = "Congratulations, you are pregnant!";
10
 
          
11
        LogCaptor<FooService> logCaptor = LogCaptor.forClass(FooService.class);
12
 
          
13
        FooService fooService = new FooService();
14
        fooService.sayHello();
15
 
          
16
        assertThat(logCaptor.getLogs("info").containsExactly(expectedInfoMessage);
17
        assertThat(logCaptor.getLogs("warn").containsExactly(expectedWarnMessage);
18
    }
19
}



You can also get all log messages by discarding the log level:

Java
 




xxxxxxxxxx
1
20


 
1
import static org.assertj.core.api.Assertions.assertThat;
2
import org.junit.Test;
3
 
          
4
public class FooServiceShould {
5
 
          
6
    @Test
7
    public void logInfoAndWarnMessages() {
8
        String expectedInfoMessage = "Keyboard not responding. Press any key to continue...";
9
        String expectedWarnMessage = "Congratulations, you are pregnant!";
10
 
          
11
        LogCaptor<FooService> logCaptor = LogCaptor.forClass(FooService.class);
12
 
          
13
        FooService fooService = new FooService();
14
        fooService.sayHello();
15
 
          
16
        assertThat(logCaptor.getLogs())
17
                .hasSize(2)
18
                .containsExactly(expectedInfoMessage, expectedWarnMessage);
19
    }
20
}



You can also get the specific log messages by an enum:

Java
 




xxxxxxxxxx
1
20


 
1
import static org.assertj.core.api.Assertions.assertThat;
2
import org.junit.Test;
3
import ch.qos.logback.classic.Level;
4
 
          
5
public class FooServiceShould {
6
 
          
7
    @Test
8
    public void logInfoAndWarnMessages() {
9
        String expectedInfoMessage = "Keyboard not responding. Press any key to continue...";
10
        String expectedWarnMessage = "Congratulations, you are pregnant!";
11
 
          
12
        LogCaptor<FooService> logCaptor = LogCaptor.forClass(FooService.class);
13
 
          
14
        FooService fooService = new FooService();
15
        fooService.sayHello();
16
 
          
17
        assertThat(logCaptor.getLogs(Level.INFO)).containsExactly(expectedInfoMessage);
18
        assertThat(logCaptor.getLogs(Level.WARN)).containsExactly(expectedWarnMessage);
19
   }
20
}



The source code is available here at Github: Github — Log Captor.

Get the latest version from Maven Central.

It also works with Lombok logging annotations, such as Log4j, Log4j2, Slf4j, and Log.

Good luck and enjoy asserting your log messages!


Further Reading

Unit Testing Best Practices: How to Get the Most Out of Your Test Automation

Unit Testing Guidelines: What to Test and What Not to Test

8 Benefits of Unit Testing

Topics:
java ,log ,log4j ,log4j2 ,logging ,lombok ,performance ,slf4j ,unit test

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}