2016-06-30 7 views
1

Unten ist eine Methode, die ich JUnit-Test für zu schreiben versucht bin:Testen, ob ein Logback-Log-Statement mit Junit aufgerufen wurde?

Methode Ich möchte Test:

//logger declared outside of method in Class 
    private static Logger LOGGER = LoggerFactory.getLogger(PersonService.class); 

    public void showOutputOfIdentifications(int age) { 

     if(age>25){ 

      LOGGER.info("Over 25"); 

     }else{ 

      LOGGER.info("25 or Under"); 

     } 
    } 

Wie kann ich testen, um zu überprüfen, dass die richtige Logback Log-Anweisung aufgerufen wurde ?

In meinen Tests habe ich versucht, die logger zu verspotten und zu überprüfen, dass es hieß, aber das hat nicht funktioniert?

Current Test Versuch:

@Test 
    public void testShowOutputOfIdentifications() throws ParseException{ 

    int age = 10; 

    Logger LOGGER_mock = mock(Logger.class); 

    //call method under test 
    showOutputOfIdentifications(age); 

    verify(LOGGER_mock).info("25 or under"); 


} 

Aktuelle Versagen Testausgang:

Wanted but not invoked: 
logger.info(
    "25 or under " 
); 

Actually, there were zero interactions with this mock. 
+2

Die zu testende Klasse hat wahrscheinlich einen statischen Logger LOGGER, der verwendet wird. Sie müssten Ihren Spott als diesen Logger injizieren. Wenn Sie einen anderen Logger erstellen, wird er nicht aufgerufen. – Fildor

+0

Danke, bitte zeigen Sie Beispiel, ich habe die ursprüngliche Methode bearbeitet, um meine statische Logger zu zeigen # – java123999

+0

Der Punkt ist: Sie müssen ** Kontrolle ** die Objekte, die Ihr "Code unter Test" verwendet. Wenn Sie ein Factory-Objekt für Sie erstellen und dieses Objekt dann innerhalb Ihrer Testklasse zugewiesen wird; Du hast keine Kontrolle. – GhostCat

Antwort

2

Sie könnten Ihre eigenen appender hinzufügen und behaupten, dass die Log-Nachricht auf diese Weise geschrieben wurde, siehe Programmatically configure LogBack appender .

Etwas wie folgt aus:

// create the mock appender 
Appender mockedAppender = Mockito.mock(Appender.class); 

// inject it 
((ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)).addAppender(mockedAppender); 

// run your test 
LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME).error("Test msg"); 

// verify using ArgumentCaptor 
ArgumentCaptor<Appender> argumentCaptor = ArgumentCaptor.forClass(Appender.class); 
Mockito.verify(mockedAppender).doAppend(argumentCaptor.capture()); 

// assert against argumentCaptor.getAllValues() 
Assert.assertEquals(1, argumentCaptor.getAllValues().size()); 
Assert.assertEquals("Test msg", ((LoggingEvent)argumentCaptor.getAllValues().get(0)).getMessage()); 

// remove the mock appender from static context 
((Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME)).detachAppender(mockedAppender); 
+0

Danke, also schreibe ich den Appender für den eigentlichen Logger oder den Mock? – java123999

+0

In einem Präzedenzfall habe ich dir gesagt, du solltest den Mock in die Klasse spritzen, um ihn zu testen. Wenn du keine Magie magst, lass es benutzt werden ... –

+0

Danke kannst du bitte Codebeispiel dazu zeigen? – java123999

0

Ich schrieb dieses mit Groovy und Spock um die Appen zu Mock.

Meine logback-test.xml Datei sieht aus wie

<configuration debug="true"> 
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/> 
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
    <encoder> 
     <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> 
    </encoder> 
</appender> 

<appender name="JSON" class="ch.qos.logback.core.ConsoleAppender"> 
    <encoder> 
     <pattern>%msg%n</pattern> 
    </encoder> 
</appender> 

<logger name="clicks" level="INFO" additivity="false"> 
    <appender-ref ref="JSON"/> 
</logger> 
<logger name="com.carsnip" level="DEBUG"/> 

<root level="INFO"> 
    <appender-ref ref="STDOUT"/> 
</root> 

Und mein Test enthält:

class LogTest extends Specification{ 
    def "should log"() { 
     given: 
     Logger root = (Logger) 
     LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); 
     Appender rootMockAppender = Mock() 
     root.addAppender(rootMockAppender); 
     Logger click = (Logger) LoggerFactory.getLogger("clicks"); 
     Appender clickMockAppender = Mock() 
     click.addAppender(clickMockAppender); 

     when: 
     click.info("HEYYYYY") 

    then: 
     0 * rootMockAppender.doAppend(_) 
     1 * clickMockAppender.doAppend(_) 
    } 
} 

Das die Additivität Attribut zu überprüfen geschrieben wird, so dass der ROOT-Logger , die höher in der Hierarchie liegt, erfasst nicht die Protokolle von unserem Clicks-Logger, der an einen anderen Ort geht.