我这里有一点问题,实在不知道如何为记录器消息实现单元测试。当然,这听起来有点奇怪,但对我来说这是一个非常有趣的话题。但让我更具体一点。
我有一些scala类和测试规范:
class Testable extends Logging {
def method() = {
// some method calls
logger.info("Message1")
}
}
class TestableSpec extends Specification with ShouldMatchers with Mockito {
"Testable instance" should {
// some important tests
"print proper log message during method call" in {
// And how to test that logger really prints proper message ("Message1")?
}
}
}
我的第一个想法是拦截底层记录器引擎消息,但由于在Testable类中使用了mixin,因此实现起来似乎有点困难,因此任何做这些事情的想法都会非常有用。
更新 我终于实施了一项测试,并决定与社区分享我的解决方案。我们不能直接模拟scalalogging.Logger类,因为它是最终的,但我们仍然可以模拟底层的slf4j Logger。澄清一个想法:
class Testable extends Logging {
def foo() = {
// ...
logger.info("Foo has been called")
}
}
// Another imports are omitted.
import com.typesafe.scalalogging.slf4j.Logger
import org.slf4j.{Logger => Underlying}
class TestableSpec extends Specification with Mockito with ShouldMatchers {
def initTestable(mocked: Underlying): Testable = {
new Testable() {
override lazy val logger = Logger(mocked)
}
}
"Testable instance" should {
"invoke logger with a proper message" in {
val mocked = mock[Underlying]
mocked.isInfoEnabled returns true // Should be set to true for test
initTestable(mocked).foo()
there was one(mocked).info("Foo has been called")
}
}
}
感谢Eric的帮助。他的回答是解决方案的关键。
答案 0 :(得分:8)
一种可能性是使用Mockito检查方法调用:
class Testable extends Logging {
def method() = {
// some method calls
logger.info("Message1")
}
}
class TestableSpec extends Specification with ShouldMatchers with Mockito {
"Testable instance" should {
"print proper log message during method call" in {
val mockLogger = mock[Logger]
val testable = new Testable {
// switch the logger with a mock instance
override val logger = mockLogger
}
testable.method()
there was one(mockLogger).info("Message1")
}
}
}
这是主要想法,但您可能需要根据您的确切特征和日志框架进行调整:
答案 1 :(得分:0)
好问题......好回答!我在Mockito mixin上遇到了一些麻烦。所以我使用Eric的方法使用Java DSL for Mockito。如果有人对此变体感兴趣,这里是稍微修改过的代码:
import com.typesafe.scalalogging.{LazyLogging, Logger, StrictLogging}
import org.mockito.Mockito
import org.mockito.Mockito._
import org.slf4j.{Logger => Underlying}
class Testable extends LazyLogging {
def foo() = {
logger.info("Foo has been called")
}
}
import org.junit.runner.RunWith
import org.scalatest.{BeforeAndAfterEach, FunSuite}
import org.scalatest.junit.JUnitRunner
import org.scalatest.matchers.ShouldMatchers
@RunWith(classOf[JUnitRunner])
class LoggerTest
extends FunSuite with ShouldMatchers with BeforeAndAfterEach {
def initTestable(mocked: Underlying): Testable = {
new Testable() {
override lazy val logger = Logger(mocked)
}
}
test("the mockito stuff") {
val mocked = Mockito.mock(classOf[Underlying])
when(mocked.isInfoEnabled()).thenReturn(true)
initTestable(mocked).foo()
verify(mocked).info("Foo has been called")
}
}