Nick
Nick

Reputation: 2907

How to inject mocked ratpack client in Groovy spock test

I'm new to Kotlin and Groovy and not sure how feasible it is to achieve this.

I have an http client that makes remote calls

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

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

Then there MyApiApp configuration with random binding and registrations

And then an AbstractModule which from what I can see an external library to create a more readable configuration:

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

MyEndpoint gets injected into the configuration of myApp and the endpoints become available. The endpoint works well but the below is a pseudocode that shows roughly what it does.

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() }
                  }
            }
         }
      }
   }
}

And now to the question. I am writing groovy integration tests and I want to make httpCall to my ratpack server but I want the subsequent calls to myClient to be mocked to eliminate dependencies.

@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
  }

And here lies the problem. The endpoint foo gets hit successfully but the myClient isn't mocked. the BindingImposition does something because it replaces myClient with one that has null HttpClient inside it.

Is it somehow possible to inject a mocked client into my endpoint? I would prefer not to create an EmbeddedApp, but to just mock MyClient. I also tried UserRegistryImpositions but so far I haven't managed to properly mock MyClient.

I have achieved this using .NET Core 2, but haven't found the way using this framework.

Any help is very appreciated. Thanks

Upvotes: 0

Views: 405

Answers (1)

Nick
Nick

Reputation: 2907

I got it to work by using interfaces

Upvotes: 0

Related Questions