如何在演员的接收方法中测试期货的构成?

时间:2016-06-26 11:17:44

标签: scala testing akka actor

我有以下演员代码:

class MyActor @Inject()(dao1: MyDao, dao2: OtherDao, eventBus: EventBus) extends Actor with ActorLogging {

  import context.dispatcher
  eventBus.subscribe(context.self, MyTopics.FooTopic)

  override def receive: Receive = {
    case Foo(name: String) => {
        dao.get(name)
          .flatMap(result => dao2.getSomeMoreStuff(result)
              .flatMap( data => //do more stuff)
          )
    }
  }
}

当演员完成处理Foo时,它将调用此未来的合成,并将在此合成完成之前移动处理另一个Foo消息,这是可以的(我认为)。

我的问题是测试这个演员:

class MyActorTest(_system: ActorSystem) extends TestKit(_system)
with WordSpecLike with Matchers with BeforeAndAfterAll
with MockitoSugar with DefaultTimeout with ImplicitSender{

  def this() = this(ActorSystem("myActorSpec"))

  override def afterAll {
    TestKit.shutdownActorSystem(system)
  }

  trait MyActorScope extends Scope {
    val myDao = mock[MyDao]
    val otherDao = mock[OtherDao]
    val eventBus = new MyEventBus()
    val myActor = TestActorRef(new MyActor(myDao, otherDao, eventBus)
  }

  "Test" must {
    "verify dao" in new MyActorScope {
        when(myDao.get(any)).thenReturn(Future.successful(("myDaoResult")))
        when(otherDao.getSomeMoreStuff(any)).thenReturn(Future.successful(("otherDaoResult")))
        eventBus.publish(new FooMessage(FooPayload("foo")))
        verify(myDao).get(any)
        verify(otherDao).getSomeMoreStuff(any)
     }
   }
}

所以这里发生的事情是myDao被验证成功,但是其他Dao不是。 我认为这是因为期货的构成并未在此消息处理结束之前发生。

有办法解决这个问题吗?演员代码是否有意义?

谢谢!

1 个答案:

答案 0 :(得分:0)

使用Timeout VerificationMode修复它

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
            <include layout="@layout/nav_header_main" />
        </LinearLayout>

    </android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>


DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        View child = getLayoutInflater().inflate(R.layout.app_bar_main, null);
        drawer.addView(child);