is there a way to mock internal service calls while writing Component testcases - wiremock

I'm writing my component level test-cases for my repository. My API calls internally a third party API which I need to mock. I don't have direct access to that API neither I can directly call it, it needs to be called from within the API calls. I need to mock in order to run the component test-cases successfully. I tried wiremock but looks like it is not working and my API is still calling the 3rd party URL. Is there any way to solve this problem. Here is my code -
Annotation at class level
#Rule
public WireMockRule wireMockRule = new WireMockRule(wireMockConfig().port(8888));
WireMockServer wm;
Started server
#BeforeEach
void setUp() {
wm = new WireMockServer(WireMockConfiguration.options().port(8888));
wm.start();
}
In the tests.
wireMockServer.start();
wm.stubFor(get("https://someurl")
.willReturn(badRequest()
.withHeader("Content-Type", "application/json")
.withBody("<response>SUCCESS</response>")));
MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders
.post(apiContextPath)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(gson.toJson(offerParams)))
.andExpect(status().isOk()).andReturn();
wireMockServer.stop();
Sorry can't paste whole code due to security reasons.

It looks like you're trying to use the JUnit 4 rule with JUnit 5, meaning the WireMock server won't be started.
Try the JUnit Jupiter extension instead: https://wiremock.org/docs/junit-jupiter/

Related

What are the modifications needed to be done to get Wiremock running?

I have a .Net Core web API solution called ReportService, which calls another API endpoint (we can call this PayrollService) to get payroll reports. So my requirement is to mock the PayrollService using Wiremock.Net.
Also currently I have a automation test case written, which will directly call the ReportService controller and will execute all the service logic, and also classes which calls PayrollService and the DB layer logic and will get the HTTP result back from the ReportService.
Please note that the Automation test cases is a separate solution. So my requirement is to run the automation test cases like before on ReportService, and the payroll service will be mocked by Wiremock.
So, what are the changes that need to happen in the codebase? Do we have to change the url of the ReportService to be the Wiremock server base url in the ReportService solution? Please let us know, and please use the terms I have used in the question regarding the project names so I am clear.
Your assumption is indeed correct, you have make the base URL which is used by ReportService configurable.
So that for your unit / integration tests you can provide the URL on which the WireMock.Net server is running.
Example:
[Test]
public async Task ReportService_Should_Call_External_API_And_Get_Report()
{
// Arrange (start WireMock.Net server)
var server = WireMockServer.Start();
// Setup your mapping
server
.Given(Request.Create().WithPath("/foo").UsingGet())
.RespondWith(
Response.Create()
.WithStatusCode(200)
.WithBody(#"{ ""msg"": ""Hello world!"" }")
);
// Act (configure your ReportService to connect to the URL where WireMock.Net is running)
var reportService = new ReportService(server.Urls[0]});
var response = reportService.GetResport();
// Assert
Assert.Equal(response, ...); // Verify
}

How and Where to use failOnUndocumentedParams in Spring Auto REST Docs?

I am working with Spring Auto REST Docs, and want to know the use of failOnUndocumentedParams, and how to use it. I want that documentation should not be generated if I miss a field from the POJO. I believe using failOnUndocumentedParams is my solution. However, I don't know how and where to use it.
#Before
public void setUp() throws IOException {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.alwaysDo(JacksonResultHandlers.prepareJackson(objectMapper))
.alwaysDo(MockMvcRestDocumentation.document("{class-name}/{method-name}",
Preprocessors.preprocessRequest(),
Preprocessors.preprocessResponse(
ResponseModifyingPreprocessors.replaceBinaryContent(),
ResponseModifyingPreprocessors.limitJsonArrayLength(objectMapper),
Preprocessors.prettyPrint())))
.apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation)
.uris()
.withScheme("http")
.withHost("localhost")
.withPort(8080)
.and().snippets()
.withDefaults(CliDocumentation.curlRequest(),
HttpDocumentation.httpRequest(),
HttpDocumentation.httpResponse(),
AutoDocumentation.requestFields(),
AutoDocumentation.responseFields(),
AutoDocumentation.pathParameters(),
AutoDocumentation.requestParameters(),
AutoDocumentation.description(),
AutoDocumentation.methodAndPath(),
AutoDocumentation.section()))
.build();
}
Here's how my mockMvc looks.
You can configure the feature when creating the request or response field snippets. In your case you want to enable the feature for all tests and thus when setting up Mock MVC:
.withDefaults(
...
AutoDocumentation.requestFields().failOnUndocumentedFields(true),
AutoDocumentation.responseFields().failOnUndocumentedFields(true),
...)
Alternatively one can enable the feature for a single test:
document("some-path",
AutoDocumentation.requestFields().failOnUndocumentedFields(true),
AutoDocumentation.responseFields().failOnUndocumentedFields(true))

How to Pass object to REST Get Method

I am using Jersey Rest implementation. There are one Rest Services Called HelloWorld. See the below code.
Please consider this code as reference not as compiled code.
#Path("helloWorld")
public class HelloWorld{
#Path("test")
#Produces(...)
#Consum(...)
#GET
public Response test(Person person){
System.out.println(person);
}
}
I am using Jersey client to sent the request.
Here My question is apart from POST method is there any way to send the object to GET method directly. Instead of QueryString.
Please let me if there is any way to do so.
Thanks
So the problem shouldn't be with the server. I did a few tests on different servers (not weblogic as I don't use it) and all of them seem to have no problems accepting a body in the GET request. The problem seem to be with the client. To test I used the following code
ClientBuilder.newClient()
.target("http://localhost:8080/api/get-body")
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true)
.request()
.method(HttpMethod.GET, Entity.text("Hello World"));
The SUPPRESS_HTTP_COMPLIANCE_VALIDATION allows us to pass a body to the request. If we didn't use this, then we would get an error.
The problem with this code, is that even though we set this override property, the client completely overrides the GET method and automatically makes it a POST method, so I would get back a 405 Method Not Allowed.
The solution I came up with is to just allow the client to set a header, e.g. X-GET-BODY-OVERRIDE, and then use a #PreMatching filter on the server side to check for this header. If the header is present, then just change the method to a GET
#Provider
#PreMatching
public class GetWithBodyFilter implements ContainerRequestFilter {
#Override
public void filter(ContainerRequestContext request) throws IOException {
String getOverride = request.getHeaderString("X-GET-BODY-OVERRIDE");
if (getOverride != null && "true".equalsIgnoreCase(getOverride)) {
request.setMethod(HttpMethod.GET);
}
}
}
Then just register the filter with the server side. On the client, you would simply need to add the header
ClientBuilder.newClient()
.target("http://localhost:8080/api/get-body")
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true)
.request()
.header("X-GET-BODY-OVERRIDE", "True")
.method(HttpMethod.GET, Entity.text("Hello World"));
This solution is good because it takes into account more than just the Jersey client, in regards with being able to send a body in the GET request.

Jena API with REST webservice using Jersey

I am using Jena API to get RDF data from Allegrograph Server. I have written a REST webservice using Jersey jar to get this data.
My java code for the webservice is as shown below:
#GET
#Path("/JENA")
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public String getData() throws RepositoryException {
AGGraphMaker maker = new AGGraphMaker(conn);
AGGraph graph = maker.getGraph();
AGModel model = new AGModel(graph);
AGQuery agQuery = AGQueryFactory.create(query);
QueryExecution qe = AGQueryExecutionFactory.create(agQuery, model);
String result = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
ResultSet rs = qe.execSelect();
While(rs.hasNext()){
byteArrayOutputStream = new ByteArrayOutputStream();
if("JSON".equalsIgnoreCase(outputFormat)){
ResultSetFormatter.outputAsJSON(byteArrayOutputStream, rs);
result = byteArrayOutputStream.toString();
System.out.println("Result is "+result);
} else if("XML".equalsIgnoreCase(outputFormat)){
ResultSetFormatter.outputAsXML(byteArrayOutputStream, rs);
result = byteArrayOutputStream.toString();
}else if("CSV".equalsIgnoreCase(outputFormat)){
ResultSetFormatter.outputAsCSV(byteArrayOutputStream, rs);
result = byteArrayOutputStream.toString();
}
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
I get no results for the SPARQL query when I deploy this web service on Tomcat server and test it using REST client app on Chrome and firefox.
But the same code(absolutely no difference in webservice code and this main method code) if I write in a plain java class and run its main method, i am getting 36 results. I am not sure what the issue is.
Please help me in this regard.
You need to separate the concerns:
Move the service logic - the bit that actually queries Allegro graph - to a separate class so that it's properly encapsulated. The API for the class should reflect its responsibilities in your application, not the way that it happens to be working at the moment.
Write JUnit tests for the service class. This is important - it gives you confidence that your service is performing its job correctly, and keeps on doing so as you develop your application.
Write your Jersey method to invoke any service object that conforms to the API of your service class.
Write one or more HTTPUnit (or similar) tests to invoke your REST API. Ideally, you'll use a mock or test double instead of the actual service. What you want to test is whether the HTTP request reaches the right method, and that method delegates to the service object with the right arguments. You're then testing (and debugging!) a smaller number of concerns.
It's much better to work with small units of functionality with a clear idea of what their responsibilities are. And you should definitely learn to work with tests - it's a big win in the medium term, even if it means a bit more learning up front!

SOAPUI : Need Sample REST APIs to test using SOAPUI Tool

Hi Can anyone let me know where I can find sample RESTFul APIs so that I can have hands on experience working on them using GET/POST/DELETE methods.
Thanks.
If you have an idea about Java, Servlet, Wildfly / Tomcat server, Mysql then you can create a basic program for Get / Post Method and deploy on the local server.
You will learn to create basic API also. The best way you install eclipse and integrate server. With Eclipse, you can easily create Servlet as it provides template and web.xml generate automatically.
Create a basic object Class. Call it in servelet fill some data.
Convert it to JSON by using GSON
#WebServlet(asyncSupported = true, urlPatterns = { "/School_getEmployee" })
public class School_Employee_servlet extends HttpServlet {
private static final long serialVersionUID = 1L;
Gson gson = new GsonBuilder().serializeNulls().create();
String json = gson.toJson(Object);
PrintWriter out = response.getWriter();
out.println(json);
}
Now you can use this servlet as API for testing.
You can use JSON-SERVER, I'm using these to make GET/PUT/POST/DELETE