17

ここで少し問題があり、ロガー メッセージの単体テストを実装する方法がまったくわかりません。もちろん、少し奇妙に聞こえますが、私にとっては非常に興味深いトピックです。しかし、もっと具体的にさせてください。

私はいくつかのスカラクラスとテスト仕様を持っています:

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")
        }
    }
}

エリックの助けに感謝します。彼の答えが解決への鍵でした。

4

2 に答える 2

3

良い質問...そして良い答えです!Mockito mixin で問題が発生しました。そのため、Mockito の Java DSL で Eric のアプローチを使用しています。誰かがこのバリエーションに興味を持っている場合は、わずかに変更されたコードを次に示します。

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")
  }
}
于 2015-12-19T23:13:40.010 に答える