如何在Groovy Spock测试中注入模拟的Ratpack客户端

时间:2018-07-05 09:58:02

标签: groovy kotlin mocking 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替换为其中具有空HttpClient的myClient。

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

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

我们非常感谢您的帮助。谢谢

1 个答案:

答案 0 :(得分:0)

我通过使用界面来使其工作