首页 > 解决方案 > 如何在 Groovy spock 测试中注入模拟的 ratpack 客户端

问题描述

我是 Kotlin 和 Groovy 的新手,不确定实现这一点有多可行。

我有一个远程调用的 http 客户端

class MyClient @Inject constructor(private val httpClient: HttpClient, private val config: MyConfig) {

  fun GetStuff(id: Id): Promise<MyResponse> { ...}
}

然后是带有随机绑定和注册的 MyApiApp 配置

然后是一个 AbstractModule,从我可以看到一个外部库来创建一个更具可读性的配置:

class ApiModule : AbstractModule() {
  protected override fun configure() {
    bind(MyEndpoint::class.java)
  }

MyEndpoint 被注入到 myApp 的配置中,并且端点变得可用。端点运行良好,但下面是一个伪代码,大致显示了它的作用。

class MyEndpoint @Inject constructor(val mClient:MyClient) : Action<Chain> {
  override fun execute(chain: Chain) {
    chain.path("foo") { ctx ->
      ctx.byMethod { method ->
        method
            .post { ->
              ctx.request.body
                  .then { requestBody ->
                    Blocking.get {
                      val id = OBJECT_MAPPER.readValue(requestBody.getText(), Id::class.java)
                      val data: ComponentResult<MyResponse> = Blocking.on(myClient.GetStuff(id))

                      data.result!!
                    }
                        .onError { throw Exception(it.message) }
                        .then { tx.response.status(HttpResponseStatus.OK.code()).send() }
                  }
            }
         }
      }
   }
}

现在问题来了。我正在编写 groovy 集成测试,我想对我的 ratpack 服务器进行 httpCall,但我希望对 myClient 的后续调用进行模拟以消除依赖关系。

@Shared UUID Id= UUID.fromString("c379ad2f-fca4-485c-a676-6988e2c8ef82")
private MyClient mockClient = GroovyMock(MyClient)
private MyEndpoint myEndpoint = new MyEndpoint(mockClient)

@AutoCleanup
private aut = new MainClassApplicationUnderTest(MyApiApp) {

    @Override
    protected void addImpositions(final ImpositionsSpec impositions) {
      impositions.add(BindingsImposition.of {
        it.bindInstance (MyEndpoint, myEndpoint)
      })
    }
  }

  @Delegate
  TestHttpClient client = aut.httpClient

  void 'Make a call and the client should be mocked'() {
    when:
    final response = client.requestSpec { spec ->
      spec.body { b ->
        b.type("application/json")
        b.text("{\"Id\": \"$Id \"}")
      }
    }.post('foo')

    then:
    1 * mockClient.GetStuff(Id) >> { throw new Exception("Fail") }

    and:
    response.status.code == 500
  }

这就是问题所在。端点 foo 被成功命中,但 myClient 未被模拟。BindingImposition 做了一些事情,因为它将 myClient 替换为其中包含 null HttpClient 的那个。

是否有可能将模拟客户端注入我的端点?我宁愿不创建 EmbeddedApp,而只是模拟 MyClient。我也尝试过 UserRegistryImpositions 但到目前为止我还没有设法正确模拟 MyClient。

我已经使用 .NET Core 2 实现了这一点,但还没有找到使用这个框架的方法。

非常感谢任何帮助。谢谢

标签: groovykotlinmockingspockratpack

解决方案


我通过使用接口让它工作


推荐阅读