I want the Unit Test to go through both, Success and Failure execution paths. How to make the test case to go to Success or Failure path?
void addRespondents()
{
http.request(POST, TEXT) {
uri.path = PATH
headers.Cookie = novaAuthentication
headers.Accept = 'application/json'
headers.ContentType = 'application/json'
body = respondentString
response.success = { resp, json ->
statusCode = 2
}
response.failure = { resp, json ->
if(resp.status == 400) {
statusCode = 3
def parsedJson = new JsonSlurper().parse(json)
}else{
autoCreditResponse = createErrorResponse(resp)
}
}
}
}
OK, it seems you use this library:
Because I never used HTTPBuilder before and it looks like a nice tool when using Groovy, I played around with it a bit, replicating your use case, but converting it into a full MCVE. I have to admit that testability for this library is in bad shape. Even the tests for the library itself are no proper unit tests, but rather integration tests, actually performing network requests instead of mocking them. The tool itself also contains to test mocks or hints about how to test.
Because the functionality heavily relies on dynamically binding variables in closures, mock-testing is somewhat ugly and I had to look into the tool's source code in order to pull it off. Nice black-box testing is basically impossible, but here is how you can inject a mock HTTP client returning a predefined mock response which contains enough information not to derail the application code:
Class under test
As you can see, I added enough data in the class to be able to run it and do something meaningful. The fact that your method returns
voidinstead of a testable result and we only have to rely on testing side effects, does not make testing easier.Spock specification
This spec covers all 3 cases for responses in the above code, using an unrolled test which returns different status codes.
Because the method under test returns
void, I decided to verify the side effect thatHTTPBuilder.requestwas actually called. In order to do this, I had to use aSpyon theHTTPBuilder. Testing for this side effect is optional, then you do not need the spy.If you have used Spock for a while, probably I do not need to explain much. If you are a Spock or mock testing beginner, probably this is a bit too complex. But FWIW, I hope that if you study the code, you can wrap your head around how I did it. I tried to use Spock label comments in order to explain it.
Console log
The console log indicates that all 3 execution paths are covered by the specification:
If you use a code coverage tool, of course you do not need the log statements I inserted into the application code. They are just for demonstration purposes.
Verifying the result of
http.request(POST, TEXT) {...}In order to circumvent the fact that your method returns
void, you can save the result ofHTTPBuilder.request(..)by stubbing the method call in the spy interaction, passing through the original result at first, but also checking for the expected result.Simply add
def actualResultsomewhere in thegiven ... andblocks (inwhenit is too late), then assign the result ofcallRealMethod()to it and then compare toexpectedResultlike this:If you prefer a data table instead of data pipes, the
whereblock looks like this:I think this pretty much covers all that makes sense to test here.