Unit test for web service (Service Reference) - xml deserialization - web-services

In Summary
I need a way to deserialize an XML string into an object normally returned by a 3rd party webservice.
Using C#.
In Detail
I have code that consumes a 3rd party Service Reference (Web Service) - so the usual stuff: we pass in a Request object and it returns a Response object.
Regarding unit testing - I'm not interested in the inner workings of the Service Reference since this is a 3rd party service. I'm only interested in two things:
Does my code generate the correct Request object?
When the Service Reference returns it's response, do I process this response correctly?
Taking each in turn:
Does my code generate the correct Request object?
This I can do. If anyone's interested in this, what I do is to replace my service reference with a RhinoMocks Mock object. In my unit test I call the method on my Mock and then check the arguments passed in, comparing the actual Request object against the expected Request object.
When the Service Reference returns it's response, do I process this response correctly?
What I want to do here is to create a RhinoMocks Stub of my service reference, so that when it's called this stub returns a response object populated with my test data.
The problem that I face is that the response objects returned by this particular 3rd party service are extremely complex. If I were to attempt to create one by hard-coding all the property values by hand then this would probably take me the best part of a whole day.
However, what I can very easily do is to capture the XML serialized response from this service. I could then easily edit it's values and store this XML in one of my unit tests.
What I'm after is an easy way to then "deserialize" this "test" XML into a response object and use this to program the response from my Stub.
Any help would be much appreciated.
Thanks
Griff

Turns out that this is quite simple:
public static object Deserialize(string xml, Type toType)
{
using(Stream stream = new MemoryStream())
{
byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
stream.Write(data, 0, data.Length);
stream.Position = 0;
var s = new XmlSerializer(toType, "http://^your url^");
return s.Deserialize(stream);
}
}
Note that if you're using XML from a SOAP request, strip the SOAP envelop off first.
Griff

Related

How do I retrieve body of client request in a spring webflux unit test?

I have a #Service which uses a WebClient to return a Mono<Something>. I want to test that the service adds the right data to the request - headers, URI, body. My test's approach is to inject a mocked WebClient.Builder into the service, and provide a WebClient with a custom exchange function:
#BeforeEach
void preProgramWebClientBuilder() {
webClient = WebClient.builder()
.baseUrl(TEST_REMOTE_BASE_URL)
.exchangeFunction(clientRequest -> {
// ...
}).build();
// webClientBuilder is the mockito-managed mock
when(webClientBuilder.baseUrl(anyString())).thenReturn(webClientBuilder);
when(webClientBuilder.build()).thenReturn(webClient);
}
This works well, for checking request host/path/query parameters/headers, with the exchange function either performing the checks itself, or setting the clientRequest aside for the test to do the checks. But I have not found a way to extract the body from the clientRequest object, to perform assertions on it.
Fully mocking the WebClient yields some ugly test initialization code, which I'd like to avoid. Is there a decent way to extract the request body from the clientRequest?
Just to mention it: I don't see how I can use a StepVerifier here. StepVerifier expects to get the Publisher to verify - and getting the body of the request as a publisher is exactly what I haven't managed to do. A WebTestClient has the same problem - I can perform a request with it, then do assertions on the response, but I can't substitute it for the regular WebClient in the service in order to perform assertions on the request emitted by the service.

JAX-RS Web service

Can anyone please help me understand the below piece of code? What does the second line doing? I am unable to break down that code. I am learning how to write webservices using JAX-RS and happened to come by this code.
String responsedata =
"{\"custId\":"+list.get(0)+",\"accountId\":"list.get(1)+"}";
return Response.status(201).entity(responsedata).build();
You're creating a Response object using fluent interface. Response.status() sets the status code and returns a Response.ResponseBuilder and sets the response entity body Response.entity() and also returns the same builder. Whenever you have a builder, you are using the Builder pattern. When you're done building the object, you call build() which will return the final object. In this case, it returns the Response object.

httptest.NewRequest vs http.NewRequest: which one to use in tests and why?

Golang has these two similar libs http and httptest and they both have the NewRequest func.
Why do we even need the httptest.NewRequest if http.NewRequest does it all?
If I need to create a multipart/multiform request for my tests, which one do I need to use?
As indicated in the documentation, httptest.NewRequest "returns a new incoming server Request, suitable for passing to an http.Handler for testing", while http.NewRequest "returns a Request suitable for use with Client.Do or Transport.RoundTrip." So, if you're passing the request directly to the handler in a unit test, use httptest.NewRequest, and if you're executing a full round-trip using http.Client, use http.NewRequest.

Logic need to checked in Unit test cases method

I have a GET method for webAPI which returns say hundred Products list. What logic should one need to check to diagnose the test as pass or fail?
Should I check for count>0 or anything else?
Ideally I should not check for product count as it may change (count==100).
Check out these useful links on unit testing with async web requests:
https://codereview.stackexchange.com/questions/85321/unit-testing-http-requests
https://msdn.microsoft.com/en-us/library/hh404088.aspx
https://codeutopia.net/blog/2015/01/30/how-to-unit-test-nodejs-http-requests/
http://www.jeremyg.net/entry/unit-testing-a-fetch-api-service-in-aurelia
http://lazamar.github.io/testing-http-requests-with-jasmine/
Why should I mock HTTP requests inside unit tests?
Suppose your client component has a variable count that it initialized to 0. Then you fire some web request, and it responds with data like this:
{
response: 500
}
where response can have any whole number value. Then count gets set to the value of response.
The basic gist of this unit test would be to mock the actual calling to the server (instead of making the api call and return the response, just return a hardcoded object). Then assert that the "count" variable is as you would expect it to be from this predefined response. You can then set up multiple cases (ie multiple tests) for each possible type of response that can be returned. Good luck!

Strategies to mock a webservice

I'm implementing a client consuming a webservice. I want to reduce dependencies and decided to mock the webservice.
I use mockito, it has the advantage vs. EasyMock to be able to mock classes, not just interfaces. But that's not the point.
In my test, I've got this code:
// Mock the required objects
Document mDocument = mock(Document.class);
Element mRootElement = mock(Element.class);
Element mGeonameElement = mock(Element.class);
Element mLatElement = mock(Element.class);
Element mLonElement = mock(Element.class);
// record their behavior
when(mDocument.getRootElement()).thenReturn(mRootElement);
when(mRootElement.getChild("geoname")).thenReturn(mGeonameElement);
when(mGeonameElement.getChild("lat")).thenReturn(mLatElement);
when(mGeonameElement.getChild("lon")).thenReturn(mLonElement);
// A_LOCATION_BEAN is a simple pojo for lat & lon, don't care about it!
when(mLatElement.getText()).thenReturn(
Float.toString(A_LOCATION_BEAN.getLat()));
when(mLonElement.getText()).thenReturn(
Float.toString(A_LOCATION_BEAN.getLon()));
// let it work!
GeoLocationFetcher geoLocationFetcher = GeoLocationFetcher
.getInstance();
LocationBean locationBean = geoLocationFetcher
.extractGeoLocationFromXml(mDocument);
// verify their behavior
verify(mDocument).getRootElement();
verify(mRootElement).getChild("geoname");
verify(mGeonameElement).getChild("lat");
verify(mGeonameElement).getChild("lon");
verify(mLatElement).getText();
verify(mLonElement).getText();
assertEquals(A_LOCATION_BEAN, locationBean);
What my code shows is that I "micro-test" the consuming object. It's like I would implement my productive code in my test. An example for the result xml is London on GeoNames.
In my opinion, it's far too granular.
But how can I mock a webservice without giving everystep? Should I let the mock object just return a XML file?
It's not about the code, but the approach.
I'm using JUnit 4.x and Mockito 1.7
I think the real problem here is that you have a singleton that calls and creates the web service so it is difficult to insert a mock one.
You may have to add (possibly package level) access to the singleton class. For example if the constructor looks something like
private GeoLocationFactory(WebService service) {
...
}
you can make the constructor package level and just create one with a mocked web service.
Alternatively you can set the webservice by adding a setter method, although I don't like mutable Singletons. Also in that case you have to remember to unset the webservice afterwards.
If the webservice is created in a method you might have to make the GeoLocationFactory extensible to substitute the mock service.
You may also look into remove the singleton itself. There are articles online and probably here on how to do that.
you really want to be mocking the results returned from the webservice to the code that will be using the result. In your example code above you seem to be mocking mDocument but you really want to pass in an instance of mDocument that has been returned from a mocked instance of your webservice and assert that the locationBean returned from the geoLocationFetcher matches the value of A_LOCATION_BEAN.
The easiest option would be to mock the WebService client,
when(geoLocationFetcher.extractGeoLocationFromXml(anyString()))
.thenReturn("<location/>");
You can modify the code to read the response xml from the file system.
Sample code can be found here: Mocking .NET WebServices with Mockito