Reputation: 22646
I would like to unit test a method which logs in the user via an external access management infrastructure. I do not know how to mock the Response response
object.
This is my code what I intend to test:
public String login(final String username, final String password) {
String baseUrl = getOpenAMApiBaseUrl();
String path = "/openam/json/authenticate";
// Response NEEDS TO BE MOCKED SOMEHOW
Response response = jaxClient.target(baseUrl + path)
.request(MediaType.APPLICATION_JSON_TYPE)
.header(HttpHeaderField.OPENAM_USERNAME, username)
.header(HttpHeaderField.OPENAM_PASSWORD, password)
.post(Entity.json(null));
int status = response.getStatus();
String jsonResponse = response.readEntity(String.class);
if (status == Response.Status.OK.getStatusCode()) {
try (JsonReader jsonReader = Json.createReader(new StringReader(jsonResponse))) {
JsonObject jsonObject = jsonReader.readObject();
String token = jsonObject.getString("tokenId");
LOGGER.info("{} have successfully logged in", username);
return token;
} catch (NullPointerException e) {
LOGGER.info("login failed, invalid json response for {}/{}", username, password);
return null;
}
}
String message = "an error occurred during logging in, http status: {}, user: {}/{}";
if (status == Response.Status.UNAUTHORIZED.getStatusCode()) {
message = "invalid credentials, http status: {}, user: {}/{}";
}
LOGGER.info(message, status, username, password);
return null;
}
Upvotes: 1
Views: 386
Reputation: 26492
Well ideally you would have to mock all the call starting from the jaxClient.target
method but in this case due to a very long chain needed to produce a mock i would suggest one of two options:
1) (preferrable) - extract the creation of the Response to a new class that specializes only in that particular operation.
Then you would declare that class as the dependency of the class under test an simply inject a mock of it with the builder method configured to return a certain Response object.
2) You can create a package level method in your class like following:
Response buildResponse(){
String baseUrl = getOpenAMApiBaseUrl();
String path = "/openam/json/authenticate";
// Response NEEDS TO BE MOCKED SOMEHOW
Response response = jaxClient.target(baseUrl + path)
.request(MediaType.APPLICATION_JSON_TYPE)
.header(HttpHeaderField.OPENAM_USERNAME, username)
.header(HttpHeaderField.OPENAM_PASSWORD, password)
.post(Entity.json(null));
}
Then @Spy your class under test and mock that method to return a Response that you desire:
@Spy
ClassUnderTest classUnderTest;
@Mock
Response responseMock;
@Before
public void init(){
MockitoAnnotations.initMocks(this);
}
@Test
public void test(){
doReturn(responseMock).when(classUnderTest).buildResponse();
// Act
classUnderTest.login(login,pass);
// Assertions
}
Upvotes: 2