Rest API mocking with wiremock : java - java

This is my utility class to mock the service
public class MockService {
public static void bootUpMockServices() throws IOException {
String orderServiceSpecification = readFile("mappings/orderServicesSpecifications.json", Charset.defaultCharset());
String singleOrder = readFile("mappings/singleOrder.json", Charset.defaultCharset());
WireMock.stubFor(WireMock.get(WireMock.urlEqualTo("/orders"))
.willReturn(WireMock.aResponse()
.withStatus(200)
.withBody(orderServiceSpecification)));
WireMock.stubFor(WireMock.get(WireMock.urlEqualTo("/orders/1"))
.willReturn(WireMock.aResponse()
.withStatus(200)
.withBody(singleOrder)));
}
public static String readFile(String path, Charset encoding)
throws IOException {
byte[] encoded = Files.readAllBytes(Paths.get(path));
return new String(encoded, encoding);
}
}
As you can see I'm mocking a GET call /orders (with all the orders) and responding with the body with all the orders kept in a json file.
I'm also calling a single order by GET call /orders/1. I'm responding it with an JSON object in a file. But I want it to be dynamic. Like when I hit it with orders/30 then, I should be dynamically fetch order with id=30 and render it.

Currently, if you want dynamic behaviour of the kind you described you'll need to write a ResponseDefinitionTransformer and register it with the WireMockServer or WireMockRule on construction.
This is documented here: http://wiremock.org/docs/extending-wiremock/#transforming-responses
Example of a transformer implementation here:
https://github.com/tomakehurst/wiremock/blob/master/src/test/java/com/github/tomakehurst/wiremock/ResponseDefinitionTransformerAcceptanceTest.java#L208-L222
What you're trying to do could be done pretty straightforwardly with a stub mapping matching on a URL regex something like /orders/(\d+) and a transformer that parses out the number part then modifies the bodyFileName on the ResponseDefinition.

Related

how to test public method which is calling private method internally

/*
this method will create the required manifest file in compatible format such that
quicksight can import data from specified s3 bucket
*/
private JSONObject CreateManifestFileJSONObject(JSONObject ManifestFile){
JSONArray URIPrefixArray= new JSONArray();
URIPrefixArray.put(PrefixLocation);
JSONObject URIPrefixJSONObject= new JSONObject();
URIPrefixJSONObject.put("URIPrefixes",URIPrefixArray);
JSONArray FileLocationsArray= new JSONArray();
FileLocationsArray.put(URIPrefixJSONObject);
JSONObject globalUploadSettings= new JSONObject();
globalUploadSettings.put("format","JSON");
ManifestFile.put("globalUploadSettings",globalUploadSettings);
ManifestFile.put("fileLocations",FileLocationsArray);
return(ManifestFile);
}
/*
this method will upload the ManifestFile to same S3 Bucket in which data files is stored
*/
private void UploadManifestFileJSONObjectToS3(JSONObject ManifestFile){
try {
AmazonS3 S3Client = new Utility().SetUpS3Client();
byte[] fileContentBytes = (ManifestFile.toString()).getBytes();
InputStream fileInputStream = new ByteArrayInputStream(fileContentBytes);
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(fileContentBytes.length);
S3Client.putObject(new PutObjectRequest(Bucket_Name, ManifestFileName, fileInputStream, objectMetadata).withCannedAcl(CannedAccessControlList.PublicRead));
}
catch(Exception exception){
exception.printStackTrace();
}
}
public void handler() {
System.out.println("inside the manifest file");
try {
JSONObject ManifestFile = new JSONObject();
ManifestFile = CreateManifestFileJSONObject(ManifestFile);
UploadManifestFileJSONObjectToS3(ManifestFile);
}
catch(Exception exception){
exception.printStackTrace();
}
I want to test handler method but handlor method is calling private methods so I do not know how to write the test class for this code.
i want to write unit test for this class please help
this is the test class I am able to create up to this point but it will not surely mock s3 behaviour
#Test
public void handler() {
ManifestFileHandler manifestFileHandler=new ManifestFileHandler();
manifestFileHandler.handler();
}
You can test private methods with the help of PowerMock provides utilities which uses reflection to do certain things.
check the below example,
https://examples.javacodegeeks.com/core-java/mockito/mockito-mock-private-method-example-with-powermock/
There are two schools of thought on unit testing private functions. The first is that you make them public (or protected or package accessible) and test them as you would a public function. The second is that if they are private they are part of the encapsulated implementation detail and you only need to test them through the public functions.
My personal view is that complicated private functions are often a sign that you are breaking the single responsibility principle and it's likely you should have logic in private functions that should be split into a separate class that can then be tested through its public methods.
With respect to the code you've posted you have a larger problem than how to test the private functions: your class depends on other classes that you don't have control over. You have no way of mocking the behaviour of those classes to test various scenarios or to verify that they have been called correctly. I suspect it is this problem that is really behind your question.
As an example, I would suggest you inject a S3Client into your class rather than create it internally through new Utility().SetUpS3Client(). That way you can mock its behaviour and verify it is called correctly by your code. Attempting to do that with the real version of this class will be challenging.
So using this model, your code might look something like:
public class ManifestFileHandler {
private final S3Client client;
public ManifestFileHandler(S3Client client) {
this.client = client;
}
private void upload(JSONObject manifestFile) {
...
client.putObject(...);
}
public void handleManifest() {
...
upload(manifestFile);
...
}
}
And your test code (using mockito):
#Test
void testManifestUpload() {
S3Client client = mock(S3Client.class);
ManifestFileHandler handler = new ManifestFileHandler(client);
handler.handleManifest();
verify(client).putObject(expectedObject);
}
If you need to capture the argument passed to putObject and assert various aspects of it then that is possible with most mocking tools (including mockito) but is beyond the scope of your question.

Unit testing for uploading to S3

I'm having trouble writing unit tests for a method that overwrites a file to a S3 bucket. The method grabs the original metadata of the file, and then overwrites the file with a new modified version and the same original metadata.
What I want the test to do is verify the inner methods like getObjectMetadata and putObject are called correctly with the right parameters
Here is the method:
public void upload(File file, String account, String bucketName) {
String key = "fakekey";
ObjectMetadata objMData = client.getObjectMetadata(bucketName, key).clone();
try {
// cloning metadata so that overwritten file has same metadata as original file
client.putObject(new PutObjectRequest(bucketName, key, file).withMetadata(objMData));
} catch(AmazonClientException e) {
e.printStackTrace();
}
Here is my test method:
#Mock
private AmazonS3 client = new AmazonS3Client();
public void testUpload() {
S3Uploader uploader = new S3Uploader(client);
File testFile = new File("file.txt");
String filename = "file.txt";
String bucketname = "buckettest";
String account = "account";
String key = account+filename;
ObjectMetadata objMetadata = Mockito.mock(ObjectMetadata.class);
when(client.getObjectMetadata(bucketname, key).clone()).thenReturn(objectMetadata);
// can I make this line do nothing? doNothing()??
doNothing.when(client.putObject(Matchers.eq(new PutObjectRequest(bucketName, key, file).withMetadata(objMData))));
uploader.upload(aFile, anAccount, bucketName);
// how do I verify that methods were called correctly??
// what can I assert here?
}
I'm getting a NullPointerException at the line in my test
when(client.getObjectMetadata(bucketname, key).clone()).thenReturn(objectMetadata);
I'm not even able to reach the method call. Honestly, what I'm pretty much asking is, how do I verify that this upload() method is correct?
The method you showed in your question uses a client instance to talk to S3. The client instance in the class to which this method belongs is either injected (at construction time, for example) or created (via a factory, perhaps). Assuming it is injected when the containing class is created then your test case might look like this:
#Test
public void testSomething() {
AmazonS3 client = Mockito.mock(AmazonS3.class);
S3Uploader uploader = new S3Uploader(client);
String bucketName = "aBucketName";
// ensures that the getObjectMetadata call fails thereby throwing the exception which your method catches
Mockito.when(client.getObjectMetadata(Matchers.eq(bucketName), Matchers.eq("fakekey")).thenThrow(new AmazonServiceException());
uploader.uploadToS3(aFile, anAccount, bucketName);
// at this stage you would typically assert that the response
// from the upload invocation is valid but as things stand
// upload() swallows the exception so there's nothing to assert against
}
#Test
public void testSomethingElse() {
AmazonS3 client = Mockito.mock(AmazonS3.class);
S3Uploader uploader = new S3Uploader(client);
String bucketName = "aBucketName";
String key = "fakekey";
File aFile = ...;
ObjectMetadata objMData = ...;
// ensures that the getObjectMetadata call succeeds thereby allowing the call to continue to the subsequent putObject invocation
Mockito.when(client.getObjectMetadata(eq(bucketName), eq(key)).thenReturn(objMData);
// ensures that the putObject call fails thereby throwing the exception which your method catches
Mockito.when(client.putObject(Matchers.eq(new PutObjectRequest(bucketName, key, file).withMetadata(objMData)).thenThrow(new AmazonServiceException());
uploader.uploadToS3(aFile, anAccount, bucketName);
// at this stage you would typically assert that the response
// from the upload invocation is valid but as things stand
// upload() swallows the exception so there's nothing to assert against
}
The above code uses Mockito to mock the AmazonS3 client, this allows you to tweak the behaviour of your client instance such that your test invocations go down the 'throw exception' paths.
On a side note the catch clauses look a little odd since AmazonS3.putObject and AmazonS3.getObjectMetadata are both declared to throw AmazonServiceException and AmazonServiceException extends AmazonClientException.
I would suggest you to use this project https://github.com/findify/s3mock.
Create a mock of S3 bucket, and then you can test what happens when the bucket you look for exist or not.

How to mock a method call using Mockito

I have the following problem using Mockito for unit testing:
I have this method:
#Override
public void handle(HttpExchange httpRequest) throws IOException {
Object[] outputResult = processRequest(httpRequest);
String response = (String) outputResult[0];
Integer responseCode = (Integer) outputResult[1];
httpRequest.sendResponseHeaders(responseCode, response.length());
OutputStream os = httpRequest.getResponseBody();
os.write(response.getBytes());
os.close();
}
And I want only to test this method, not the processRequestMethod that is called internally (that I would like to test separately in anthoer test), so I need to mock it and to check at the end of the test that the methods write and close of the OutputStream class have been called.
I have tried two ways, but no luck with none of them:
#Test
public void handleTest() throws IOException {
RequestHandler requestHandler=mock(RequestHandler.class);
String response = "Bad request";
int responseCode = HttpURLConnection.HTTP_BAD_REQUEST;
Object[] result={response,responseCode};
when(requestHandler.processRequest(anyObject())).thenReturn(result);
when (httpExchange.getResponseBody()).thenReturn(outputStream);
requestHandler.handle(httpExchange);
Mockito.verify(outputStream,times(1)).write(anyByte());
Mockito.verify(outputStream,times(1)).close();
}
With the code above, the processRequest method is not called, but neither is the handle method that I want to test, so the test is failing in the line:
Mockito.verify(outputStream,times(1)).write(anyByte());
Saying that this method was not called at all.
However if I add the parameter CALL_REAL_METHODS when creating the mock, like this:
#Test
public void handleTest() throws IOException {
RequestHandler requestHandler=mock(RequestHandler.class,CALLS_REAL_METHODS);
String response = "Bad request";
int responseCode = HttpURLConnection.HTTP_BAD_REQUEST;
Object[] result={response,responseCode};
when(requestHandler.processRequest(anyObject())).thenReturn(result);
when (httpExchange.getResponseBody()).thenReturn(outputStream);
requestHandler.handle(httpExchange);
Mockito.verify(outputStream,times(1)).write(anyByte());
Mockito.verify(outputStream,times(1)).close();
}
Then the processRequest method that I want to skip is actually called when the method executes this line:
when(requestHandler.processRequest(anyObject())).thenReturn(result);
Any clues of what can be wrong?
in your test instead of
RequestHandler requestHandler=mock(RequestHandler.class,CALLS_REAL_METHODS);
use Mockito.spy():
RequestHandler requestHandler=spy(RequestHandler.class);
doReturn(result).when(requestHandler).processRequest(httpRequest);
you may want the doReturn().when() form rather than the when().thenReturn() because the first does not execute the method whereas the latter does.
On the other hand I'd prefer to move processRequest() to another class where you can inject an instance of into RequestHandler which would make mocking more straight...

How to mock Inputstream to load Properties in Java

I wanted to test the IOException and IllegalArgumentException thrown by properties.load(in) method. As per the documentation here OracleDoc it says the load method throws IOException - if an error occurred when reading from the input stream. IllegalArgumentException - if the input stream contains a malformed Unicode escape sequence.
Here is my code:
public class PropertiesRetriever {
private String foo;
private String foo1;
private Properties properties;
/**
* Injects the properties file Path in the {GuiceModule}
* Calls {#link PropertiesRetriever#loadPropertiesPath(String) to load the
* properties file.
*/
#Inject
public PropertiesRetriever(#Named("propertiesPath") String propertiesPath, Properties properties)
throws IOException {
this.properties = properties;
loadPropertiesPath(propertiesPath);
}
/**
* Loads the properties file as inputstream.
*
*/
public void loadPropertiesPath(String path) throws IOException {
InputStream in = this.getClass().getResourceAsStream(path);
properties.load(in);
}
Here, a method:
properties.load(in)
throws IOException and IllegalArgumentException. I wanted to test this methods in JUnit testing. Is there anyway I can call these methods.
You can do it by refactoring your code a little. That and use Mockito or some other mocking framework to create an InputStream that behaves as you desire (throw exceptions):
public void loadPropertiesPath(String path) throws IOException {
// Always close streams you open!
try (InputStream in = getIStream(path)) {
properties.load(in);
}
}
private InputStream getIStream(String path) {
InputStream in = this.getClass().getResourceAsStream(path);
return in;
}
You can use mockito to create a partial mock of your object; mock getIStream(String) to return a mock InputStream. Set up the mock to throw the exception you want when InputStream::read(byte[]) gets called.
If you do not want to use PowerMock then you can change the visibility of getIStream(String) to default. Then plain mockito will do the job:
#Test
public void exceptionTest() throws IOException {
PropertiesRetriever pr = new PropertiesRetriever();
PropertiesRetriever prSpy = spy(pr);
InputStream isMock = mock(InputStream.class);
doReturn(isMock).when(prSpy).getIStream(anyString());
doThrow(new IllegalArgumentException("CRASH!")).when(isMock).read(any());
prSpy.loadPropertiesPath("blah");
}
You have two choices. Either provide some test files, that will create expected errors, or pass mock of Stream to Properties retriever as parameter. So instead of propertiesPath parameter, you will have directly inputStream (this approach may just move your problem somewhere else).
If you decide to pass Stream as a parameter, there are some tips, how to mock it: Mocking Java InputStream

web service client in java

I want to generate a client program using the service
I am unable to display the results, how can I do so?
import java.rmi.RemoteException;
public class searchtry {
public static void main(String[] args) throws RemoteException {
SearchRequest request=new SearchRequest();
SearchRequestType1 type1=new SearchRequestType1();
query.setAppId("*********************************"); //Windows Live gave this id for using that service
query.setSources(new SourceType[]{SourceType.Web});
query.setQuery("Java");
aratip.setParameters(request);
SearchResponseType0 answer= client.search(type1);
System.out.println(answer.toString());
}
For starters, calling
answer.toString();
May or may not result in anything (usually won't). You might just get a string that represents the instance, not the string you're expecting. You need to find a method on SearchResponseType0 that will give you the string representation of the response. Perhaps a method like getContent() or getResponse() or something like that but without understanding more about the web service it's difficult to give you more help. Bottom line, you're using the wrong method to attempt to get the string content of the result.
It looks like your are using the bing-search-java-sdk. They have a very nice example on their homepage you might want to look at:
BingSearchServiceClientFactory factory = BingSearchServiceClientFactory.newInstance();
BingSearchClient client = factory.createBingSearchClient();
SearchRequestBuilder builder = client.newSearchRequestBuilder();
builder.withAppId(applicationId);
builder.withQuery("msdn blogs");
builder.withSourceType(SourceType.WEB);
builder.withVersion("2.0");
builder.withMarket("en-us");
builder.withAdultOption(AdultOption.MODERATE);
builder.withSearchOption(SearchOption.ENABLE_HIGHLIGHTING);
builder.withWebRequestCount(10L);
builder.withWebRequestOffset(0L);
builder.withWebRequestSearchOption(WebSearchOption.DISABLE_HOST_COLLAPSING);
builder.withWebRequestSearchOption(WebSearchOption.DISABLE_QUERY_ALTERATIONS);
SearchResponse response = client.search(builder.getResult());
for (WebResult result : response.getWeb().getResults()) {
System.out.println(result.getTitle());
System.out.println(result.getDescription());
System.out.println(result.getUrl());
System.out.println(result.getDateTime());
}

Categories

Resources