引言
按测试驱动开发(TDD, Test Driven Development)的理念,测试代码应先于产品代码被编写,这样不仅保证了产品代码的测试覆盖率,并且可以强制开发者在设计之初就考虑代码将如何被使用,如何才能易于测试。
Akka基于ScalaTest框架,提供了akka-testkit模块来支持单元测试和集成测试的编写。
加入依赖
修改build.sbt并加入相应的测试模块:
1 | libraryDependencies ++= Seq( |
运行sbt update更新依赖。
加入测试代码
现在我们给RedPakcetClient加上相应的测试代码:
1 | import akka.actor.{ActorSystem, Actor, Props} |
辅助组件
akka-testkit提供了一系列组件来帮助我们实现测试代码:
-
ImplicitSender:
akka-testkit提供了一个testActor来作为隐式的消息发送者,通常我们会使用testActor作为被测试actor的对端,这样做的好处在于:- 让代码专注于被测Actor自身的消息收发,与外界Actor的交互由
testActor代理。 - 通过隐式的
testActor,可以直接调用Akka提供的一系列断言方法。
- 让代码专注于被测Actor自身的消息收发,与外界Actor的交互由
-
TestKit: 提供了一个与Actor交互的基础框架,以及一系列的测试断言来帮助我们处理Actor的回复消息。
expectMsg[T](d: Duration, msg: T): T指定时间内期望收到回复的msg.expectMsgPF[T](d: Duration)(pf: PartialFunction[Any, T]): T使用指定的偏函数对收到的回复消息进行验证。expectNoMsg(d: Duration)在指定的时间内期望不收到任何消息。fishForMessage(max: Duration, hint: String)(pf: PartialFunction[Any, Boolean]): Any指定时间内,持续接受消息直到偏函数返回True。- 更多的方法请参考akka文档。
-
TestActorRef: 不同于普通的ActorRef, TestActorRef可以让我们直接访问到内部Actor的状态。虽然打破封装通常不是一个好的实践,但是在某些情况下可以方便测试代码的实现。
1 | val testRedPacketClient = TestActorRef(Props(classOf[RedPacketClient], testActor)) |
测试日志消息
akka-testkit也支持对日志消息的测试,客户端代码需要:
- 使用
TestEventListener来替代通常的事件处理器。 - 使用
akka.testkit.EventFilter来检查日志信息。
运行测试
从github下载代码,并执行sbt test即可运行测试。
如果遵循测试驱动开发,希望每次保存代码修改后自动执行测试,可以运行命令:
1 | sbt |