简体   繁体   中英

Unit testing for rest call

I am currently at a loss with unit testing a method that calls a REST service within it for messaging a status to this service.

I have a method like:

public void informService(String state, BusinessObject bus) {

  Client client = null;
  Response response = null;
  try {

    client = new ResteasyClientBuilder()
                            .establishConnectionTimeout(10L, TimeUnit.MINUTES)
                            .socketTimeout(10L, TimeUnit.MINUTES)
                            .build();

      WebTarget target = client.target("my.url");

      MyDTO dto = new MyDTO();
      dto.state = state;

      response = target.request("application/json").put(Entity.json(dto));

      boolean ok = handleReturnCode(response.getStatus(), bus.getId());

      if (!ok) {
        throw new RuntimeException("Invalid status" + response.getStatus());
      }

      return ok;

  } catch (Exception e) {
  } finally {
    try {
      if (response != null) {
        response.close();
      }
      if (client != null)
        client.close();
    } catch (Exception e) {
  }
}

So in the method there is a call to a REST service which is evaluated within the method. How can I unit test this behaviour?

When UnitTesting against a network service always move the actual network call into another Class and hide it behind an Interface .

Then you can create a fake object for that Interface.
In you test you then inject the fake service instead of the real one.

//Interface for your service
public interface MyService{
    void sendJson(JsonObject json, Callback callback);

    interface Callback{
        void onResult(int resultCode);
    }
}

//Class you want to test
public void MyClass{
    private MyService myService;

    public MyClass(MyService myService){
        this.myService = myService;
    }

    public void informService(String state, BusinessObject bus) {
         //Do the network call with your service and handle the response
    }

}

Now in your test you can create a FakeService extending MyService and return whatever response code you want to test.
Of course you can also use a mocking framework like Mockito to create your fakes, than you do not have to write them yourself.

I said about power mock so i write to you what i've written:

Let's say this is your method:

public boolean informService(String state) {

        Client client = null;
        client = new ClientBuilder().build(true);

        boolean ok = client.getOK();

        if (!ok) {
            throw new RuntimeException("Invalid status");
        }

        return ok;

}

It is easy version of your method, but we still create new Builder here, class is named TestRest. For testing this clearly bad written piece of code we need to use PowerMock:

@RunWith(PowerMockRunner.class) //clear
@PrepareForTest(TestRest.class) //clear 
public class TestRestTest {

    @Test
    public void shouldReturnOKWhenOK() throws Exception{

        ClientBuilder builder = PowerMock.createMock(ClientBuilder.class); //prepare ClientBuilder mock to inject while test

        TestRest tested = new TestRest(); //tested class, of course

        PowerMock.expectNew(ClientBuilder.class).andReturn(builder); //What we expect when certain class will be instantiated using new, like in our example Builder

        EasyMock.expect(builder.build(true)).andReturn(new Client(true)); //What we want to obtain, of course you will return some mocked object i think, especially that this is Unit test and you will want to test logic of method, not other classes

        PowerMock.replay(builder, ClientBuilder.class); // change to replay mode to get configured expectation

        assertTrue(tested.informService("state")); //clear

        PowerMock.verify(builder, ClientBuilder.class);
    }

}

Also here you have maven dependencies:

    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-easymock-release-full</artifactId>
        <version>1.6.4</version>
    </dependency>
    <dependency>
        <groupId>org.easymock</groupId>
        <artifactId>easymock</artifactId>
        <version>3.4</version>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-all</artifactId>
        <version>1.10.8</version>
    </dependency>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM