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.