【问题标题】:Injecting mock actors into a Spray route for testing将模拟演员注入到喷雾路线中进行测试
【发布时间】:2015-03-18 00:32:00
【问题描述】:

我部门的多个小组已经开始使用 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)
    }
}

换句话说,每个端点都有一个对应的actor,并且在路由内部,该类型的actor将与请求上下文一起启动,一条消息将传递给它,并且该actor将处理 HttpResponse &停下来。

我一直都有足够简单的路由树,我只对 Actor 本身进行了单元测试,并让集成测试来处理路由测试,但我在这里被否决了。所以问题在于,对于单元测试,人们希望能够将 FooService 替换为 MockFooService

有处理这种情况的标准方法吗?

【问题讨论】:

    标签: scala unit-testing akka spray spray-test


    【解决方案1】:

    我会选择一个蛋糕模式,您可以在最后一刻混合实现:

    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
    }
    

    可以以相同的蛋糕模式方式覆盖此方法,并且对于测试,您甚至可以完全避免使用演员。

    【讨论】:

    • 这是一个很好的方法。如果可能的话,隐藏演员是要走的路。
    • 所以这与我尝试做的非常接近,而且更优雅一点,在某种程度上解决了我尝试做事的方式。无论出于何种原因,我最终将 Props 创建函数完全拆分为一个单独的特征树 - 回想一下我一开始试图做一些花哨的事情并不断遇到类型擦除问题,所以到那时我已经失去了森林的树木.谢谢,将确保我没有错过我们基本问题中的一些微妙之处(有些还有其他复杂性,但 c'est la vie)
    • 事实证明,我说的是真的,而我解决问题的尝试导致了一个过于复杂的解决方案,而我一直想要的是 this。有一些异常情况,但我通过 FP 解决了这个问题。世界上一切都好。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 2014-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多