假设我有一条触发/log
控制器方法的路由MyController.iDoLogSometimes
:
class MyController extends Controller{
def iDoLogSometimes = Action{
request =>
val hasProperty: Boolean = ??? //A request property check
if(hasProperty) Logger.info("prop exist")
else Logger.debug("prop does not exist")
}
}
现在,在测试中,我可以发送FakeRequest
我需要的任何属性;在我的方法中涵盖这两种情况。
但是我不知道如何捕获Logger
输出并使用某种must
匹配器。
请注意我的logback.xml
文件夹中有conf/
;我确实在控制台中看到了日志;在测试过程中。
答案 0 :(得分:2)
使用大多数Java / Scala日志库可靠地捕获日志输出并不容易,因为日志是全局的,并且访问是并发的。 然而,如果你愿意,你可以试一试。我最近在Play test做了这个。我使用的是specs2而不是scalatest,但捕获日志的想法是一样的:
import ch.qos.logback.classic.Logger
import ch.qos.logback.classic.spi.ILoggingEvent
import ch.qos.logback.core.AppenderBase
import org.slf4j.LoggerFactory
...
"not complain about invalid User-Agent headers" in {
// This test modifies the global (!) logger to capture log messages.
// The test will not be reliable when run concurrently. However, since
// we're checking for the *absence* of log messages the worst thing
// that will happen is that the test will pass when it should fail. We
// should not get spurious failures which would cause our CI testing
// to fail. I think it's still worth including this test because it
// will still often report correct failures, even if it's not perfect.
import scala.collection.immutable
def recordLogEvents[T](block: => T): immutable.Seq[ILoggingEvent] = {
/** Collects all log events that occur */
class RecordingAppender extends AppenderBase[ILoggingEvent] {
private val eventBuffer = ArrayBuffer[ILoggingEvent]()
override def append(e: ILoggingEvent): Unit = synchronized {
eventBuffer += e
}
def events: immutable.Seq[ILoggingEvent] = synchronized {
eventBuffer.to[immutable.Seq]
}
}
// Get the Logback root logger and attach a RecordingAppender
val rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME).asInstanceOf[Logger]
val appender = new RecordingAppender()
appender.setContext(rootLogger.getLoggerContext)
appender.start()
rootLogger.addAppender(appender)
block
rootLogger.detachAppender(appender)
appender.stop()
appender.events
}
withServerAndConfig()((Action, _) => Action { rh =>
Results.Ok(rh.headers.get("User-Agent").toString)
}) { port =>
def testAgent[R: AsResult](agent: String) = {
val logMessages = recordLogEvents {
val Seq(response) = BasicHttpClient.makeRequests(port)(
BasicRequest("GET", "/", "HTTP/1.1", Map(
"User-Agent" -> agent
), "")
)
response.body must beLeft(s"Some($agent)")
}
logMessages.map(_.getFormattedMessage) must contain(contain(agent))
}
// These agent strings come from https://github.com/playframework/playframework/issues/7997
testAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 11_0_3 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Mobile/15A432 [FBAN/FBIOS;FBAV/147.0.0.46.81;FBBV/76961488;FBDV/iPhone8,1;FBMD/iPhone;FBSN/iOS;FBSV/11.0.3;FBSS/2;FBCR/T-Mobile.pl;FBID/phone;FBLC/pl_PL;FBOP/5;FBRV/0]")
testAgent("Mozilla/5.0 (Linux; Android 7.0; TRT-LX1 Build/HUAWEITRT-LX1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.98 Mobile Safari/537.36 [FB_IAB/FB4A;FBAV/148.0.0.51.62;]")
testAgent("Mozilla/5.0 (Linux; Android 7.0; SM-G955F Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/62.0.3202.84 Mobile Safari/537.36 [FB_IAB/Orca-Android;FBAV/142.0.0.18.63;]")
}
}