I have a function in controller class that calls a Rest Easy web service which returns a response. I need to unit test that particular function.
public void createOrderRequest(OrderModel orderModel, ResourceBundle resourceBundle, AspectModel aspectModel) {
try {
LOG.debug("Creating order request");
OrderReq orderRequest = new OrderReq();
orderRequest.getHeader().setDestination("http://localhost:8080/middleware/ws/services/txn/getReport");
orderRequest.setUserId("abc");
OrderResp response = (OrderResp) OrderService.getInstance().getOrderService().sendRequest(orderRequest);
if (response.getHeader().getErrorCode() == ErrorCode.SUCCESS.getErrorCode()) {
LOG.debug("Successfully send order request");
orderModel.setErrorDescription("Order successfully sent");
aspectModel.set(orderModel);
}
} catch (Exception ex) {
LOG.error("Error while sending order request: " + ex.getMessage());
}
}
I want to mock the order request object OrderReq and response object OrderResp. My intention is to create mock response for the rest easy web service request. How can I achieve it ?
The most simple way is to move the object creation into a help method which you can override in a test:
public void createOrderRequest(OrderModel orderModel, ResourceBundle resourceBundle, AspectModel aspectModel) {
try {
LOG.debug("Creating order request");
OrderReq orderRequest = createOrderReq();
....
}
}
/*test*/ OrderReq createOrderReq() { return new OrderReq(); }
Using package private (default) visibility, a test can override the method (since they are in the same package).
Alternatively, you can create a factory and inject that.
Related
I'm trying to run some integration tests on my code and I use a MockRestServiceServer from spring-boot-test in order to set up the expected requests.
I have one call that is called many times while running my test, but it seems not to persist during the test. My test looks like this:
#Test
void getHealthStatus() {
try {
RequestBuilder request = get("/actuator/hc").contentType("application/json");
MockServerBinder.bindPersistentThingworxPropertiesCall(
mockServer,
requestTo(new URI(String.format("%sProperties/TestProp", thingworxUrl))),
objectMapper.writeValueAsString(new PingResponse(DashboardIndicator.HEALTHY, 200))
);
DashboardStatusModel expectedResult = new DashboardStatusModel();
expectedResult.addResult("spring",service.getAppHealth());
expectedResult.addResult("thingworx", service.getThingworxAvailability());
assertOpenUrl(request);
MvcResult result = mockMvc.perform(get("/actuator/hc").contentType("application/json"))
.andExpect(status().isOk())
.andReturn();
DashboardStatusModel actualResult = objectMapper.readValue(result.getResponse().getContentAsString(), DashboardStatusModel.class);
assertEquals(expectedResult.getResults().get("spring"), actualResult.getResults().get("spring"));
assertEquals(expectedResult.getResults().get("thingworx").getStatus(),actualResult.getResults().get("thingworx").getStatus());
assertEquals(expectedResult.getResults().get("thingworx").getData().get("url"), actualResult.getResults().get("thingworx").getData().get("url"));
} catch (Exception e) {
fail("Unable to perform REST call on GDP-API", e);
}
}
As additional information:
mockServer is created in a superclass like this:
protected static MockRestServiceServer mockServer;
#BeforeEach
public void configureMockServer() {
mockServer = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();
}
MockServerBinder.bindPersistentThingworxPropertiesCall() is a helper class that looks like this:
public static void bindPersistentThingworxPropertiesCall(MockRestServiceServer mockServer, RequestMatcher request, String responseJSONasString){
mockServer.expect(ExpectedCount.once(), request)
.andExpect(method(HttpMethod.GET))
.andRespond(withStatus(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(responseJSONasString));
}
assertOpenUrl(request); is a function that checks if a URL doesn't have any authentication by using a MockMVC:
public void assertOpenUrl(RequestBuilder request){
try{
mockMvc.perform(request).andExpect(status().isOk());
} catch (Exception e) {
fail("Unable to perform REST call on GDP-API", e);
}
}
When I run this test, the expectedResult.addResult("thingworx", service.getThingworxAvailability()); will be able to use the MockRestServiceServer, but the assertOpenUrl(request); line will fail, because MockRestServiceServer doesn't expect anymore calls to the endpoint binded in MockServerBinder.bindPersistantThingworxPropertyCall(). This does not happen if I Copy & Paste MockServerBinder.bindPersistantThingworxPropertyCall() under the existing one, so I think it's a problem with how I binded the request in the first place.
From what I understand ExpectedCount.manyTimes() should keep this request during the test.
Is this not true or is there another way I should bind my request so that it stays available during the entire test?
PEBCAK issue.
As you can see in the bindPersistentThingworxPropertiesCall(), I actually didn't use ExpectedCount.manyTimes(). I didn't catch that. Changed it and now it works.
I'm trying to make a service in reactive java,
another service will send me requests.
I catch these requests and want to run methods according to the incoming URI
Here I receive a request from another service and run the desired method:
public Mono<Response> requestResponse(Request message, ByteBuf metadata) {
return controller.startMethod(message)
.onErrorResume(error -> Mono.just(buildResponse(error.getMessage(), message, Status.STATUS_INTERNAL_SERVER_ERROR)))
.switchIfEmpty(Mono.just(buildResponse("NULL", message, Status.STATUS_BAD_REQUEST)))
.doOnNext(logResponse());
}
This is the launch itself, the method is located by the annotation and the http method
public Mono<Response> startMethod(Request message) {
for (Method method : clazz.getDeclaredMethods()) {
if (isNecessaryMethod(method, message)) {
try {
return (Mono<Response>) method.invoke(context.getBean(clazz), initParameters(method, message));
} catch (Throwable e) {
return Mono.error(e);
}
}
}
return Mono.error(new PathNotFound());
}
Subsequently, the method should run, this is an example:
#Request(url = "/save-token", method = POST)
public Mono<Response> saveToken(String token) {
return Mono.empty();
}
I would like to know how to properly process method.invoke(...) so that everything works reactively and correctly
I am using a method where it calls another REST API to retrieve an ID from the DB. When I run the veracode scan for the class I am getting Security flaw "Server-side Request Forgery" at below line.
response = resttemplate.getForEntity(resturl, String.class);
Not sure How to fix this issue. Any help is appreciated. Below is my full code for that method.
public static String getIDFromDB(String resturl) {
String id = null;
RestTemplate resttemplate = new RestTemplate();
ResponseEntity<String> response = new ResponseEntity<>(HTTPStatus.OK)
try {
response = resttemplate.getForEntity(resturl, String.class);
if (response.getStatusCode == HTTPStatus.OK && response.getBody.trim() != null) {
id = response.getBody.trim() ;
}
} Catch(Exception e) {
log.error("failed to get msgID: {}", e);
}
}
This is because you are allowing in your code to pass the resturl completely in your code, so it enables the attacker to bypass and route the URL to their intended destination.
To avoid this, so should externalise and refer the URL having domain and the application contexts with operation name in config files or dB
I am trying to use JUnit4 test a utility method that takes a javax.ws.rs.core.Response as an input parameter. The method looks at the Response attributes and takes some action based on the response code. When I just create a response in my test method and submit it using:
Response resp = Response.status(Status.INTERNAL_SERVER_ERROR).entity(respMessage).build();
ResponseParser.parseResponse(resp);
My utility method throws:
java.lang.IllegalStateException: RESTEASY003290: Entity is not backed by an input stream
at org.jboss.resteasy.specimpl.BuiltResponse.readEntity(BuiltResponse.java:231)
at org.jboss.resteasy.specimpl.BuiltResponse.readEntity(BuiltResponse.java:218)
My util class is basically:
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status.Family;
public class ResponseParser {
public static void parseResponse(Response response) {
String errorResp = "";
if (!response.getStatusInfo().getFamily().equals(Family.SUCCESSFUL)) {
int errorCode = response.getStatus();
errorResp = response.readEntity(String.class);
}
}
}
How can I create a response that will be properly backed by a stream as expected by resteasy? I looked at quite a few similar questions but they mostly seemed to be centered around testing or mocking an endpoint call. I just want to test my parsing method.
I did end up doing what #albert_nil suggested. Here is the relevant code from my test class. MessageParseUtil.parseReportResponse(mockResponse); is the utility method that is being tested.
#Test
public void parse_Report_Response_400_Test() {
String respMessage = "400 : Validation error occurred. Invalid Parm: employeeID";
Response mockResponse = buildMockResponse(Status.INTERNAL_SERVER_ERROR, respMessage);
try {
MessageParseUtil.parseReportResponse(mockResponse);
fail("Expected parseReportResponse() to throw error but none thrown.");
} catch (RestClientException e) {
Assert.assertEquals("Expected to status code to be 400 but was " + e.getStatusCode() + " instead.", 400, e.getStatusCode());
Assert.assertEquals("The error message was missing or not correct.", respMessage, e.getErrorMessage().getErrorMessageList().get(0));
}
}
private Response buildMockResponse(Status status, String msgEntity) {
Response mockResponse = mock(Response.class);
Mockito.when(mockResponse.readEntity(String.class)).thenReturn(msgEntity);
Mockito.when(mockResponse.getStatus()).thenReturn(status.getStatusCode());
Mockito.when(mockResponse.getStatusInfo()).thenReturn(status);
return mockResponse;
}
Mock the Response with some unit testing framework, like Mockito. Then you will be able to declare what to return on each response method call, or even check if a method has been called.
I have three or more types of request that come in form of JSON data and convert to object.
Let's say that there is a request:
{
"id":1,
"type":"0",
"url":
"http://stackoverflow.com"
}
And I want to build some sort of conncetion factory that allows me to get pages like that:
Request request = new Request(json);
Response response = request.execute();
Of course the execute method has different implementation for each of the request's types.
I have a prototype that is written in plain JavaSE and I want to migrate to Spring Framework and also get some feedback about my code if it has problems. First of all I built a SimpleRequest that just obtains the page and returns the body.
class SimpleRequest implements Request{
Package requestData;
#Override
public Connection.Response execute() throws IOException {
Connection.Response response = Jsoup
.connect(requestData.getUrl())
.execute();
return response;
}
public void bind(Package requestData){
this.requestData = requestData;
}
}
This method just fetch the page. Nothing interesting.
Also I have RequestTemplate that prepare request:
class RequestTemplate{
Package requestData;
RequestFactory requestFactory = new RequestFactory();
Request request;
public RequestTemplate(Package requestData){
this.requestData = requestData;
try {
request = requestFactory.getRequestInstance(requestData.getType());
request.bind(requestData);
}catch (Exception e){
e.printStackTrace();
}
}
public Connection.Response execute(){
Connection.Response connection = null;
try{
connection = request.execute();
}catch (Exception e){
e.printStackTrace();
}
return connection;
}
}
This method obtains an object based of RequestType;
And of course I have RequestFactory that has a description of objects and create new Instances of them.
class RequestFactory{
public Request getRequestInstance(RequestType type) throws Exception {
switch (type){
case SIMPLE:
return new SimpleRequest();
default:
throw new Exception("Error");
}
}}
So we check the RequestType type matching with the enum list and return new instance.
I also what to implement something like that in my small project that are based on Spring Framework and there are two issues.
As I understand the code above is a bit messy and has some performance problems. I think that I'll use the code to serve lots of connection so that I have to optimize it somehow because of memory limit and so on.
Integration with Spring. It's a framework so I think there should be some features that could make my life easier. I've read about FactoryBean, but haven't caught how to wire it with my task. As I mentioned above that the code is a bit messy and i think that i created to much abstraction.
Thanks.