我有一个相当简单的场景,我想做一个直接的集成测试。高级概述,是:
- 我有一个
actor
,它响应一个名为PlaceOrder
的消息 - 我想在收到
PlaceOrder
时验证这个参与者publishes
另一条消息,在这种情况下是OrderPlaced
问题是,对于集成测试,我可以断言消息已通过ExpectMsg<OrderPlaced>
发布。但是,我也希望它能调用任何处理该消息的参与者?
也许我对TestKit
的理解在这里是不正确的,但当从中继承时,你会得到:
ActorOfAsTestActorRef<T>
ActorOf<T>
Sys.ActorOf(...)
我的印象是,ActorOf<T>
和Sys.ActorOf(...)
将表现得像一个真正的参与者系统,而ActorOfAsTestActorRef<T>
将是严格的单元测试的理想选择,并吞下参与者可能发送的任何消息。
例如,以下是我的两个参与者:
public class PlaceOrderActor : ReceiveActor
{
public PlaceOrderActor()
{
this.Receive<PlaceOrderMessage>(
message =>
{
this.Handle(message);
});
}
private void Handle(PlaceOrderMessage message)
{
Context.ActorOf(Props.Create<Foo>()).Tell(new OrderPlaced(message.CustomerId, message.OrderItems));
}
}
public class Foo : ReceiveActor
{
public Foo()
{
this.Receive<OrderPlaced>(
m =>
{
});
}
}
我的测试是这样的。奇怪的是,我必须自己协调这个集成测试,即我检查OrderPlaced
是否已经发布,然后显式地向Foo
:发送消息
[TestFixture]
public class IntegrationTest : TestKit
{
[Test]
public void When_Placing_An_Order()
{
var message = new PlaceOrderMessage(
"123",
new List<OrderItem>
{
new OrderItem("Product ABC", 2)
});
this.ActorOfAsTestActorRef<PlaceOrderActor>().Tell(message);
var orderPlaced = this.ExpectMsg<OrderPlaced>();
//if (orderPlaced != null)
//{
//this.ActorOfAsTestActorRef<Foo>().Tell(orderPlaced);
//}
}
}
我所期望的是,通过发送消息PlaceOrder
,它应该在处理OrderPlaced
时调用Foo
。我不应该在测试中把这些部分注释掉吗?
这能做到吗?还是我完全错了?
提前感谢,DS.
您的PlaceOrderActor
没有对FooActor
的引用,它响应Sender
,后者是Testkit参与者。
如果您希望FooActor
接收OrderPlaced
消息,则需要在PlaceOrderActor.Handle()
方法中告诉它该消息。您可能需要将FooActor
创建为PlaceOrderActor
的子级,或者如果它在系统中的其他位置,则需要解析对它的引用(在这种情况下,系统中根本没有运行FooActor
)。这在您的实际(即非测试)系统中是如何工作的,还是到目前为止只作为测试代码存在?
请注意,如果您将OrderPlaced
消息发送给FooActor
,并且不将任何消息告知PlaceOrderActor
的发送方,则在您的测试方法中不会产生可观察到的影响,因此您的FooActor
将需要直接响应原始发送方,或者返回PlaceOrderActor
,后者反过来可以响应原始发送方。