Wiremock and Spring Integration - 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))

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.

Mockito Multipart file argument matcher

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

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

Gmail Api Java Client - Use mockito/powermock example to mock Gmail API calls

We are using the Gmail API Java Client version 1.19.0. Is there anyone that has implemented successfully a working mock object that could be used for stubing requests such as:
gmailClient.users().history().list("me").setStartHistoryId(startHistoryId).setPageToken(pageToken).execute();
Essentially, we would like to stub the above call and create a specific response, to test different business scenarios.
Please check below a working example of the above question. No need to use powermock. Mockito is only needed.
#Before
public void init() throws Exception{
ListHistoryResponse historyResponse = new ListHistoryResponse();
historyResponse.setHistoryId(BigInteger.valueOf(1234L));
List<History> historyList = new ArrayList<>();
History historyEntry = new History();
Message message = new Message();
message.setId("123456");
message.setThreadId("123456");
List<Message> messages = new ArrayList<>();
messages.add(message);
historyEntry.setMessages(messages);
historyList.add(historyEntry);
mock = mock(Gmail.class);
Gmail.Users users = mock(Gmail.Users.class);
Gmail.Users.History history = mock(Gmail.Users.History.class);
Gmail.Users.History.List list = mock(Gmail.Users.History.List.class);
when(mock.users()).thenReturn(users);
when(users.history()).thenReturn(history);
when(history.list("me")).thenReturn(list);
when(list.setStartHistoryId(BigInteger.valueOf(123L))).thenReturn(list);
when(list.setPageToken(null)).thenReturn(list);
when(list.execute()).thenReturn(historyResponse);
}
you can mock the classes are long as they're not final, etc. what's the limitation here? (haven't looked at the source code for the Google java client libraries but shouldn't be gmail-specific--if you've found someone doing it for another Google java client API you should be able to re-use it).
There is also MockHttpTransport helper class for such a scenario. Please consult with documentation chapter HTTP Unit Testing
HttpTransport transport = new MockHttpTransport() {
#Override
public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
return new MockLowLevelHttpRequest() {
#Override
public LowLevelHttpResponse execute() throws IOException {
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse();
response.addHeader("custom_header", "value");
response.setStatusCode(404);
response.setContentType(Json.MEDIA_TYPE);
response.setContent("{\"error\":\"not found\"}");
return response;
}
};
}
};

Geb Reporter / Extension to retrieve Test Status

I am attempting to replace some custom java selenium extensions by utilizing geb. I have hit a bit of a brick wall when I attempt to utilize a grid in the cloud (i.e. SauceLabs). When my tests complete, it'd be nice to send an update back to indicate whether or not the test has failed or succeeded. To utilize this, I need the sessionId from the RemoteWebDriver instance. This can be obtained in a custom Reporter, however I can't determine the success with this interface. Since I am extending the GebReportingSpec, I attempted to create my own custom version, which had a custom Junit rule to track success or failure:
public class TestSuccess extends TestWatcher {
boolean success;
String message;
#Override
protected void starting(Description d) {
message = d.getMethodName();
}
#Override
protected void succeeded(final Description description) {
System.out.println("Test Success [succeeded] " + description);
this.success = true;
}
#Override
protected void failed(final Throwable e, final Description description) {
System.out.println("Test Success [failed] " + description);
this.success = false;
}
public boolean isSuccess() {
return success;
}
#Override
public String toString() {
return message + " success: <" + success + ">.";
}
}
I then added that to my CustomReportingSpec:
class CustomReportingSpec extends GebReportingSpec {
/* I also tried creating this as a RuleChain with:
* #Rule TestRule chain = RuleChain.outerRule(
super._gebReportingSpecTestName).around(new TestSuccess());
* however, this results in a NPE. Placing the super rule in the around
* still results in a NPE.
*/
#Rule public TestSuccess _gebTestSuccesswatcher = new TestSuccess();
// I never see this called
void report() {
System.out.println("Custom Reporting Spec: " + _gebTestSuccesswatcher + "\t")
super.report()
}
}
I have also attempted to set this up in a custom reporter:
public CustomReporter extends ScreenshotAndPageSourceReporter implements Reporter {
#Rule
public TestSuccess _gebTestSuccesswatcher = new TestSuccess();
#Override
public void writeReport(Browser browser, String label, File outputDir) {
System.out.println("Custom Reporter: " + _gebTestSuccesswatcher);
super.writeReport(browser, label, outputDir)
}
}
However, regardless of whether or not my test fails, the success method on the watcher seems to be called. Here is my sample test:
class OneOff extends CustomReportingSpec {
def "Check One off"() {
when:
go "http://www.google.com"
then:
1 == 2
}
}
And the output:
Custom Reporter: null success: <false>.
Test Success [succeeded] Check One off(OneOff)
As you can see the success method is called upon completion of this failing test. If I modify the test to pass (i.e. 1 == 1), here is my output:
Custom Reporter: null success: <false>.
Test Success [succeeded] Check One off(OneOff)
Is there any way for me to get this Rule to work properly in the Custom Reporter? Or is there a way to get the browser instance in an extension? I've followed this guide to create a custom annotation and listener, but I can't access the Browser object. I have attempted adding an #Shared onto the declaration of the browser, but it isn't pulling the one in the Geb Configuration.
Your TestSuccess class doesn't work correctly due to a known limitation in Spock's TestRule support. Due to subtle differences between Spock's and JUnit's test execution model, calling base.evaluate() from a TestRule will not throw an exception in Spock, even if the test has failed. In many cases this won't make a difference, but for TestWatcher it will.
This is the only known limitation in Spock's rule support, and hopefully we'll find a way to overcome it at some point. There is no such semantic mismatch when using MethodRule.
If you want to implement your requirement with the help of a JUnit rule (which I think is fine), MethodRule is probably the better choice anyway. In contrary to TestRule, MethodRule provides access to the test instance, which will allow you to grab the session ID with browser.driver.sessionId.

Resources