【问题标题】:Akka - Test that function from test executedAkka - 从执行的测试中测试该功能
【发布时间】:2015-01-21 09:15:16
【问题描述】:

我有以下特点

trait MyTrait{

  def printHelloWorld(){
    println("hello world")
  }

}

case object SayHello

class MyActor extends Actor with MyTrait{

   def recieve = {
       case SayHello => printHelloWorld
   }
} 

现在我正在尝试创建单元测试,然后测试 Say Hello Object 调用打印 hello 消息

"My Actor" should{
   "println hello msg if SayHello sent" in{
      val myTraitMock = mock[MyTrait]

      val myActor = system.actorOf(Props(new MyActor))
      myActor ! SayHello

      Thread.sleep(500)
      there was atLeastOne(myTraitMock).printHelloMessage
   }
} 

但是,此单元测试始终为绿色。即使我用简单的 println 方法替换了这个方法。

有没有其他方法可以测试这种情况?

【问题讨论】:

    标签: scala akka scalatest specs2


    【解决方案1】:

    这个怎么样:

    trait MyActor extends Actor{self:MyTrait
    
       def recieve = {
           case SayHello => printHelloWorld
       }
    }
    
    class MyMainActor extends MyActor with MyTrait
    
    "My Actor" should{
    "println hello msg if SayHello sent" in{
         class MockActor extends MyActor with SomeMyTrait
    
          val x = new MockActor
          val myActor = system.actorOf(Props(x))
          myActor ! SayHello
    
          Thread.sleep(500)
          there was atLeastOne(x).printHelloMessage
       }
    

    一般来说,对于演员来说,我不喜欢上面的测试。 Akka Test-kit 很棒。我强烈建议看看它。

    我会做的:

    trait MyTrait{
    
      def printHelloWorld(){
        println("hello world")
    
      }
    
    }
    
    case object SayHello
    case object Printed
    
    class MyActor extends Actor with MyTrait{
    
       def recieve = {
           case SayHello => printHelloWorld
                            sender ! Printed
       }
    } 
    
    import akka.actor.ActorSystem
    import akka.testkit.{ TestProbe, ImplicitSender, TestKit }
    import org.scalatest.matchers.ShouldMatchers
    import org.scalatest.{ BeforeAndAfterAll, FunSuite }    
    import scala.concurrent.duration._
    
    class MyTest extends TestKit(ActorSystem("MyTest1"))
      with FunSuite
      with BeforeAndAfterAll
      with ShouldMatchers
      with ImplicitSender{
    
      override def afterAll() { system.shutdown() }
      test("MyTrait is called when triggered") {
        val x = TestProbe()
        val myActor = system.actorOf(Props(new MyActor))
        myActor.send(x, SayHello)
        x.expectMsg(Printed)
    
    }
    

    【讨论】:

    • 你需要 libraryDependencies += "org.scalatest" %% "scalatest" % "1.9.1" % "test"libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % "2.2.3" 作为依赖项
    • 很好,我真的很喜欢 Akka-test,但是 MyActor 不应该向发件人返回任何消息。它只是“一劳永逸”,我可以在测试期间将其扩展为其他特征,将消息返回给发件人。这是我看到的唯一选项。
    【解决方案2】:

    您可以测试打印到EventFilter 的内容。所以如果你的演员会打印这样的消息:

    case _ => log.info(printMessage)
    

    然后你可以测试

    EventFilter.info(start="hello world", occurences=1).intercept {
      MyActor ! SayHello
    }
    

    【讨论】:

      【解决方案3】:

      我知道这是一个老问题,但我有相同的用例(即发即弃),我想出了一个使用 Probe 的简单解决方案:

      case object SayHello
      
      class MyActor(f: () => Unit) extends Actor{ // pass function as a parameter
        def receive = {
          case SayHello => f()
        }
      }
      

      现在如果你想创建一个测试:

        "test" {
          val probe = TestProbe()
      
          case object Executed
      
          def mockF():Unit = {
            println("test")
            probe.ref ! Executed
          }
      
          val testActor = TestActorRef(Props(new MyActor(mockF)))
          testActor ! SayHello
          //probe.expectMsg blocks the thread, so it'll wait for Executed message.
          probe.expectMsgPF(){case  Executed => 1}
      
        }
      

      如果你不想将函数作为参数传递,那么你可以对 trait 做同样的事情:

      trait MyTraitImpl extends MyTrait{
        def printHelloWorld(){
          println("hello world")
            }
      }
      
      trait MyTrait{
        def printHelloWorld()
      }
      
      case object SayHello
      
      class MyActor extends Actor{
        myTrait:MyTrait =>
      
        def receive = {
          case SayHello => printHelloWorld
        }
      }
      

      和测试:

        "test" {
          val probe = TestProbe()
      
          case object Executed
      
          trait MyTraitMock extends MyTrait{
            def printHelloWorld(){
              println("hello world")
      
              probe.ref ! Executed
            }
          }
      
          val testActor = TestActorRef(Props(new MyActor() with MyTraitMock))
          testActor ! SayHello
      
          probe.expectMsgPF(){case  Executed => 1}
      
        }
      

      【讨论】:

      • 我不确定这是否适用于所有情况,但在我的情况下,我需要验证是否调用了注入对象的某个方法,所以它工作得很好。测试探针不是必需的,至少对于 Akka.NET 来说不是,您可以访问由 TestKit 创建的底层测试参与者:this.TestActor.Tell("foo");this.ExpectMsg("foo");
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-29
      • 2016-03-25
      • 1970-01-01
      相关资源
      最近更新 更多