将模拟演员注入 Spray 路线进行测试
Injecting mock actors into a Spray route for testing
我部门的多个小组已经开始使用 Spray 来开发基于 REST 的 Web 服务,并且都运行遇到了类似的问题,到目前为止还没有很好的解决方案。
假设您有以下情况:
FooService extends Actor { ??? }
然后在其他地方:
path("SomePath") {
id =>
get {
requestContext =>
// I apologize for the janky Props usage here, just an example
val fooService = actorRefFactory.actorOf(Props(new FooService(requestContext)))
queryService ! SomeMessage(id)
}
}
换句话说,每个端点都有一个对应的角色,并且在路由内部,将使用请求上下文启动该类型的角色,将向其传递一条消息,该角色将处理HttpResponse & 停止。
我一直有足够简单的路由树,我只对 Actors 本身进行了单元测试,并让路由测试由集成测试处理,但我在这里被否决了。所以问题是对于单元测试,人们希望能够用 MockFooService
替换 FooService
是否有处理这种情况的标准方法?
我会选择蛋糕模式,您可以在最后一刻混合实施:
trait MyService extends HttpService with FooService {
val route =
path("SomePath") { id =>
get { requestContext =>
val fooService = actorRefFactory.actorOf(fooProps(requestContext))
queryService ! SomeMessage(id)
}
}
}
trait FooService {
def fooProps(requestContext: RequestContext): Props
}
trait TestFooService extends FooService {
def fooProps(requestContext: RequestContext) =
Props(new TestFooService(requestContext))
}
trait ProdFooService extends FooService {
def fooProps(requestContext: RequestContext) =
Props(new FooService(requestContext))
}
trait MyTestService extends MyService with TestFooService
trait MyProdService extends MyService with ProdFooService
我是用文本编辑器写的,所以我不确定它是否能编译。
如果你想在没有演员的情况下进行测试,你可以提取这两行:
val fooService = actorRefFactory.actorOf(fooProps(requestContext))
queryService ! SomeMessage(id)
进入某种方法并在其背后隐藏一个演员。例如:
def processRequest[T](msg: T): Unit = {
// those 2 lines, maybe pass other args here too like context
}
可以用相同的蛋糕模式方式覆盖此方法,对于测试,您甚至可以完全避免使用演员。
我部门的多个小组已经开始使用 Spray 来开发基于 REST 的 Web 服务,并且都运行遇到了类似的问题,到目前为止还没有很好的解决方案。
假设您有以下情况:
FooService extends Actor { ??? }
然后在其他地方:
path("SomePath") {
id =>
get {
requestContext =>
// I apologize for the janky Props usage here, just an example
val fooService = actorRefFactory.actorOf(Props(new FooService(requestContext)))
queryService ! SomeMessage(id)
}
}
换句话说,每个端点都有一个对应的角色,并且在路由内部,将使用请求上下文启动该类型的角色,将向其传递一条消息,该角色将处理HttpResponse & 停止。
我一直有足够简单的路由树,我只对 Actors 本身进行了单元测试,并让路由测试由集成测试处理,但我在这里被否决了。所以问题是对于单元测试,人们希望能够用 MockFooService
替换 FooService是否有处理这种情况的标准方法?
我会选择蛋糕模式,您可以在最后一刻混合实施:
trait MyService extends HttpService with FooService {
val route =
path("SomePath") { id =>
get { requestContext =>
val fooService = actorRefFactory.actorOf(fooProps(requestContext))
queryService ! SomeMessage(id)
}
}
}
trait FooService {
def fooProps(requestContext: RequestContext): Props
}
trait TestFooService extends FooService {
def fooProps(requestContext: RequestContext) =
Props(new TestFooService(requestContext))
}
trait ProdFooService extends FooService {
def fooProps(requestContext: RequestContext) =
Props(new FooService(requestContext))
}
trait MyTestService extends MyService with TestFooService
trait MyProdService extends MyService with ProdFooService
我是用文本编辑器写的,所以我不确定它是否能编译。
如果你想在没有演员的情况下进行测试,你可以提取这两行:
val fooService = actorRefFactory.actorOf(fooProps(requestContext))
queryService ! SomeMessage(id)
进入某种方法并在其背后隐藏一个演员。例如:
def processRequest[T](msg: T): Unit = {
// those 2 lines, maybe pass other args here too like context
}
可以用相同的蛋糕模式方式覆盖此方法,对于测试,您甚至可以完全避免使用演员。