Mockito Multipart file argument matcher - mockito

I am trying to have an integration test that throwns an exception for a void method to simulate a downed service. The method has a string param and a multipart file as a param and it does not seem to be working even though an exception is thrown for a void method with two string parameters.
Working integration test:
#Test
#DisplayName("500 response -- downed case mgmt microservice")
public void downedCaseMgmt() throws Exception {
BDDMockito.doThrow(new RuntimeException("mocking an error")).when(reportEventService).reportDocUpload(ArgumentMatchers.any(String.class), ArgumentMatchers.anyString());
//Rest assured portion
given().
multiPart("file", xlsxGoodFile).
params(paramsMap).
when().
post("").
then().
statusCode(500);
}
Non-working integration test:
#Test
#DisplayName("500 response -- downed object storage")
public void downedObjectStorage() throws Exception {
BDDMockito.doThrow(new RuntimeException("mocking an error")).when(objectStorageService).saveFileToObjectStorage(ArgumentMatchers.anyString(), ArgumentMatchers.any(File.class));
//Rest assured portion
given().
multiPart("file", xlsxGoodFile).
params(paramsMap).
when().
post("").
then().
statusCode(500);
}

Turns out that the function saveFileToObjectStorage had a null value because of the mockbean on objectStorageService and the fact that I was mocking a return. Error on my part and I resolved it with the following code:
#Test
#DisplayName("500 response -- downed db")
public void downedDb() throws Exception {
BDDMockito.doThrow(new RuntimeException("mocking an error")).when(excelDataRepository).
save(ArgumentMatchers.any());
//Rest assured portion
given().
multiPart("file", xlsxGoodFile).
params(paramsMap).
when().
post("").
then().
statusCode(500);
}
NOTE: the any() of ArgumentMatchers

Related

How to mock two APIs with MockWebServer Android test cases

I am performing instrumentation testing, in that I am invoking one of the activities which call 2 APIs when activity is created.
Now I want to write instrumentation test cases for this activity, where I have to mock the API response with mockWebServer of mockito. My mocking code works fine when I call one single API, but it fails when two APIs are getting called simultaneously.
Even there is another scenario let's say, we have API to fetch recent message data, but before that, we always authenticate the user by sending refresh token.
In such cases, we need to call API which authenticates the user and then another API to fetch message data. Hence we need to call 2 APIs one after another, let's say in a single method. How will I mock authentication API response and messages API response while writing test cases of that single method?
How should I deal with this issue? Is there any other approach to deal with such a situation where we need to call more than one API at the same time?
Also, I have used SystemClock.sleep(4000); as my callbacks were getting performed asynchronously.
Below is my code to mock API:
public class MyAPIActivityTest {
#Rule
public InstantTaskExecutorRule mInstantTaskExecutorRule = new InstantTaskExecutorRule();
#Rule
public ActivityTestRule<MyAPIActivity> myAPIActivityTestRule = new ActivityTestRule<>(MyAPIActivity.class, true, false);
MockWebServer mockWebServer;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void checkVisibilityOfTaskListMockedValidData() throws Exception {
myAPIActivityTestRule.launchActivity(null);
String fileName = "json_files/valid_api_response.json";
mockWebServer = new MockWebServer();
int PORT_NUMBER = 50205;
mockWebServer.start(PORT_NUMBER);
ApiUrls.BASE_QUERY_URL = mockWebServer.url("/").toString();
mockWebServer.enqueue(new MockResponse()
.setBody(getStringFromFile(getContext(), fileName)));
SystemClock.sleep(4000);
Assert.assertEquals(View.VISIBLE, myAPIActivityTestRule.IvDataIsPresent.getVisibility());
Assert.assertEquals(View.GONE, myAPIActivityTestRule.IvDataNotPresent.getVisibility());
}
#After
public void tearDown() throws Exception {
mockWebServer.shutdown();
}
public static String convertStreamToString(InputStream inputStream) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line).append(StringCharacters.NEW_LINE);
}
reader.close();
return stringBuilder.toString();
}
public static String getStringFromFile(Context context, String filePath) throws Exception {
final InputStream stream = context.getResources().getAssets().open(filePath);
String text = convertStreamToString(stream);
stream.close();
return text;
}
}
Any help is appreciated. Thanks in advance.

How to validate a REST Assured request across multiple java methods?

I am writing REST Assured tests using Cucumber.
Here is my feature file:
Given I want to GET a client
When I request a client
Then the status code is "theStatusCode"
And the id returned is "expectedClientId"
The below method is called within the Step Definition of the "And" in my feature file
public void validateResponseBody(String expectedClientId){
RestAssured.given()
.when()
.get(completeURL)
.then()
.statusCode(Integer.parseInt(theStatusCode))
.and()
.body("Client.Id", equalTo(expectedClientId));
}
This method currently works, but how do I split the validation?
I.e. how can I break this up to validate the Status Code in one method, & validate the Client Id in another method without having to send the request twice?
Save response to variable:
public void validate() {
ValidatableResponse response = RestAssured.given()
.when()
.get(completeURL)
.then();
validateStatusCode(response, statusCode);
validateResponseBody(response, expectedClientId);
}
public void validateStatusCode(ValidatableResponse response, String statusCode) {
response
.statusCode(Integer.parseInt(theStatusCode));
}
public void validateResponseBody(ValidatableResponse response, String expectedClientId) {
response
.body("Client.Id", equalTo(expectedClientId));
}
I suggest to make changes in Feature File.
New File should be given below. You don't need a when statement here.
Scenario: I want to GET a client
Given I request a client
Then the status code is "theStatusCode"
And the id returned is "expectedClientId"
#Given("I request a client$")
public void validate()
{
ValidatableResponse validatableResponse = RestAssured.given()
.when()
.get(completeURL)
.then();
}
#Then("the status code is \"([^\"]*)\"$")
public void validateStatusCode(String statusCode)
{
validatableResponse.assertThat().statusCode(Integer.parseInt(theStatusCode));
}
#And("the id returned is \"([^\"]*)\"$")
public void validateClientId(String expectedClientId)
{
validatableResponse.assertThat().body("Client.Id", equalTo(expectedClientId));
}

Webapi 2 global exception handling not raised

I'm uising web api 2 to develop services for a client, to manage errors we are using a ExceptionsFilterAttribute, but as you know, in this level not all exception are catched.
Some errors are raised in protected void Application_AuthenticateRequest(Object sender, EventArgs e) and I want to handle them and send a custom message to our client to give him more details about the error, to solve this I create a GlobalExceptionHandler
public class GlobalExceptionHandler: ExceptionHandler
{
//A basic DTO to return back to the caller with data about the error
private class ErrorInformation
{
public string Message { get; set; }
public DateTime ErrorDate { get; set; }
}
public override void Handle(ExceptionHandlerContext context)
{
//Return a DTO representing what happened
context.Result = new ResponseMessageResult(context.Request.CreateResponse(HttpStatusCode.InternalServerError,
new ErrorInformation { Message="We apologize but an unexpected error occured. Please try again later.", ErrorDate=DateTime.UtcNow }));
//This is commented out, but could also serve the purpose if you wanted to only return some text directly, rather than JSON that the front end will bind to.
//context.Result = new ResponseMessageResult(context.Request.CreateResponse(HttpStatusCode.InternalServerError, "We apologize but an unexpected error occured. Please try again later."));
}
}
In WebApiConfig i added this line :
config.Services.Replace(typeof(IExceptionHandler), new GlobalExceptionHandler());
The the Application_AuthenticateRequest raise some errors but GlobalExceptionHandler is never reached.
Do you have any idea how can I solve this issue ?
Thanks in advance.
Application_AuthenticateRequest does not come in the Web API pipeline. So if an exception is thrown in this method those can be caught by the Web API exception handler, because the exception is thrown before the Web API pipeline is started.
There are two ways to do this:
Either change the authentication mechanism and use Web API Authentication(IAuthenticationFilter) instead of Application_AuthenticateRequest.
If this project has only Web API related controllers, not like MVC and all.
Or use Application_Error in the Global.asax.cs file to catch the exception thrown in Application_AuthenticateRequest

Wiremock and Spring Integration

I have a flow in Spring integration, which works as follows
Read from MQ--> Do a Message Transformation-->Send the transformed message to an Api
Now in my integration test, I am trying to mock the Api out and I tried 2 flavours but did not succeed.
Here is the test with Wiremock flavour (also posted on Wiremock Github)
String requestBody = TestUtil.createSampleInputMessage(rNumber);
System.out.println("Expected Post msg by EvApiClient :" + requestBody);
stubFor(post(urlEqualTo(TestUtil.EVENT_URL))
//.withHeader("Content-Type", equalTo("application/json"))
//.withRequestBody(equalToJson(requestBody))
);
ResponseEntity response = restTemplate.getForEntity("http://localhost:9966/__admin", String.class);
System.out.println("Printing Expected response :" + response);
sendToJmsOutChannel.send(MessageBuilder.withPayload(TestUtil.createSampleInputMessage(receiptNumber)).build());
verify(postRequestedFor(urlEqualTo(TestUtil.EVENT_URL)));`
The failure I get is
com.github.tomakehurst.wiremock.client.VerificationException: A request was unmatched by any stub mapping. Closest stub mapping was: expected:<
POST
/pa/his/v1/ev> but was:<
POST
/pa/his/v1/ev>
Here is the test with Spring's MockRestServiceServer
#Before
public void setup() throws PdsListenerException, URISyntaxException {
mockServer = MockRestServiceServer.createServer(restTemplate);
}
#Test
public void test_001_success() throws InterruptedException, JSONException, URISyntaxException {
rNumber = TestUtil.generateRNumber();
String requestBody = TestUtil.createSampleInputMessage(rNumber);
mockServer.expect(once(), requestTo("http://localhost:9966" + TestUtil.EVENT_URL))
.andRespond(withCreatedEntity(new URI(TestUtil.EVENT_URL)));
sendToJmsOutChannel.send(MessageBuilder.withPayload(TestUtil.createSampleInputMessage(rNumber)).build());
mockServer.verify();
}
The failure I get is
java.lang.AssertionError: Further request(s) expected leaving 1 unsatisfied expectation(s).
0 request(s) executed.
I am not sure why the matching is failing. Is there anyone that can point out where I should be looking at.
Actually found out what the problem was with WireMock, and I will be using this flavour.
What I needed to change is
#ClassRule
public static WireMockClassRule wireMockRule = new WireMockClassRule(9966);
#Rule
public WireMockClassRule instanceRule = wireMockRule;
...
instanceRule.stubFor(post(urlPathEqualTo(Constants.EVENT_URL))
...
instanceRule.verify(1, postRequestedFor(urlEqualTo(TestUtil.EVENT_URL)));
Basically use the instance of the WireMockRule for stubbing and verifying, and not as I was doing before.
stubFor(post(urlEqualTo(TestUtil.EVENT_URL))

How can I test a MessageBodyWriter for a List<Some>?

I have a JAX-RS resource method.
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public List<Some> list() {
final List<Some> list = get();
// list and each elements are ok.
return list;
}
The problem is that application/xml generates an 500 without any specific server(tomcat) log.
application/json works fine.
I check JAXB-marshaller for every element in list.
How can I debug this? How can I test any MessageBodyWriter for List<Some>?
UPDATE
The root cause of this problem (500 without a error log) is a wrongly JAXB-annotated class.
I created an ExceptionMapper<Exception> as #peeskillet suggested.
#Provider
public class MyExceptionMapper implements ExceptionMapper<Exception> {
#Override
public Response toResponse(final Exception exception) {
exception.printStackTrace(System.err);
return Response.serverError().build();
}
}
Then I could see what error JAXB made. I still don't understand why any JAXB-error is not reported.
"How can I debug this?"
Sometimes when errors/exceptions aren't being logged, I'll create an
ExceptionMapper<Throwable or Exception>
and just print the stack trace. If the exception is being thrown in the JAX-RS context, it should go through the mapper.
See more about exception mapping

Resources