我是 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 实现了这一点,但还没有找到使用这个框架的方法。
非常感谢任何帮助。谢谢