Search code examples
javaunit-testingloggingmockitopowermockito

Powermock: Mocking static final logger


I am trying to write tests that check whether certain lines have been logged. I googled for a while but I cannot figure out why LOG is not replaced.

Class to test:

public class Example {
    private static final Logger LOG = LoggerFactory.getLogger(Example.class);

    public void foo(...)
    {
       if(...)
         LOG.warn("Warning");
       //...
    }
}

Test:

@RunWith(PowerMockRunner.class)
@PrepareForTest({LoggerFactory.class})
public class MyTest
{
    @Mock
    Logger logger;

    @InjectMocks
    private final Example example = new Example();

    @Test
    public void test1() {
        PowerMockito.mockStatic(LoggerFactory.class);
        logger = PowerMockito.mock(Logger.class);
        PowerMockito.when(LoggerFactory.getLogger(Example.class)).thenReturn(logger);

        example.foo(...);

        Mockito.verify(logger).warn("Warning");
    }
}

SLF4J is used and PowerMock 1.7.1.

PS: Replacing private static final Logger LOG is no option in this project.


Solution

  • You are creating your subject too early. You arrange the mock well after the subject has already been created.

    create the subject after arranging the static mock

    @RunWith(PowerMockRunner.class)
    @PrepareForTest({LoggerFactory.class})
    public class MyTest {
    
        @Test
        public void test1() {
            //Arrange
            Logger logger = PowerMockito.mock(Logger.class);
    
            PowerMockito.mockStatic(LoggerFactory.class);           
            PowerMockito.when(LoggerFactory.getLogger(Example.class)).thenReturn(logger);
    
            Example example = new Example();
    
            //Act
            example.foo(..);
    
            //Assert
            Mockito.verify(logger).warn("Warning");
        }
    }