我想使用Tcp IO管理器对一个将自己绑定到本地端口的actor进行单元测试,例如
IO(Tcp) ! Bind(self, new InetSocketAddress("localhost", port))
Run Code Online (Sandbox Code Playgroud)
我理想的做法是使用TestProbe代替IO管理器.这将具有不打开TCP连接的单元测试的额外好处.
这是可能的,如果是这样,有人可以提供一个如何做的例子吗?
可能有几种方法可以实现这一目标.我会传递一对,希望一个适合你.请记住,调用IO(Tcp)只会产生一个ActorRef.所以你需要做的就是找到一种方法来模拟/步入该调用,然后使用该actor参与.这里有几个代码示例显示了几个解决方案(类似DI):
第一个设置一个方法来返回tcp管理器,然后在单元测试中覆盖它.
class Actor1 extends Actor{
import context._
import Tcp._
def receive = {
case "connect" =>
tcp ! Bind(self, new InetSocketAddress("localhost", 8080))
}
def tcp:ActorRef = IO(Tcp)
}
class Actor1Spec(_system:ActorSystem) extends TestKit(_system) with Specification{
import Tcp._
def this() = this(ActorSystem("test"))
trait scoping extends Scope{
val tcpProbe = TestProbe()
val testRef = TestActorRef(new Actor1{
override def tcp = tcpProbe.ref
})
}
"A request to connect" should{
"send a message to connect to the Tcp Manager" in new scoping{
testRef ! "connect"
tcpProbe.expectMsg(Bind(testRef, new InetSocketAddress("localhost", 8080)))
}
}
}
Run Code Online (Sandbox Code Playgroud)
第二个非常相似,但是将tcp管理器传递给构造函数.
class Actor2(tcpManager:ActorRef) extends Actor{
import context._
import Tcp._
def receive = {
case "connect" =>
tcpManager ! Bind(self, new InetSocketAddress("localhost", 8080))
}
}
class Actor2Spec(_system:ActorSystem) extends TestKit(_system) with Specification{
import Tcp._
def this() = this(ActorSystem("test"))
trait scoping extends Scope{
val tcpProbe = TestProbe()
val testRef = TestActorRef(new Actor2(tcpProbe.ref))
}
"A request to connect" should{
"send a message to connect to the Tcp Manager" in new scoping{
testRef ! "connect"
tcpProbe.expectMsg(Bind(testRef, new InetSocketAddress("localhost", 8080)))
}
}
}
Run Code Online (Sandbox Code Playgroud)
这些中的任何一个都可以为你工作,但是再一次,只要你明白这个召唤IO(Tcp)只是回归一个就没有真正的魔力ActorRef