Junit testing with Spring – part 2

In my previous post on the argument (Junit testing with Spring), I skipped a very interesting part of testing attributes in the code which are inside methods.

In these cases, Mockito it’s very helpful to solve the problem.

Starting from the above article, I created a Web Controller which is tested in developer environment using a JUnit test and I extended the user’s information stored adding a Session object “LastName”.


@RequestMapping(method = RequestMethod.GET, value = "/lastname")
public String getLastName(HttpSession sessionObj, @RequestParam String firstname, ModelMap model) 
throws InterruptedException {

/*
* Check the session before Query Database
*/
if (sessionObj.getAttribute("LastName") == null) {
TableData tableData = jdbcDao.getData(firstname);

if (tableData != null)
model.addAttribute("lastname", tableData.getLast_name());
else
model.addAttribute("lastname", "");

sessionObj.setAttribute("LastName", tableData.getLast_name());
}
else
model.addAttribute("lastname", sessionObj.getAttribute("LastName"));

return "index";

}

How can I check the session value in my JUnit test class? I cannot instantiate am HttpSession object ’cause it’s an interface unlike the Model object.

Mockito helps me to create the object and put it as the parameter of the method.

HttpSession sessionObj = Mockito.mock(HttpSession.class);

Now I must check the object value and, from the Junit test, you get in the highlight line:


@Test
public void testDataDb() throws InterruptedException
{
String firstName = "Larry";
String lastName = "Bird";

TableData tableData = new TableData();

tableData.setFirst_name(firstName);
tableData.setLast_name(lastName);

when(jdbcDao.getData(firstName)).thenReturn(tableData);

ModelMap model = new ModelMap();

controller.getLastName(sessionObj, firstName, model);

assertEquals(model.get("lastname"), lastName);
assertEquals(sessionObj.getAttribute("LastName"), lastName);
}

The result is unexpected…The test fails and, if you look inside the value, you get a null value.

Remember, you’re using a fake object created by Mockito which should be “educated” about what answer in base of any input.

The when keyword can help us to achieve the aim, but it must be used in an “extended” way.

Map<Object, Object> attributes;

@Before
public void setup()
{
sessionObj = Mockito.mock(HttpSession.class);

attributes = new HashMap<Object, Object>();

when(sessionObj.getAttribute(anyString())).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock aInvocation) throws Throwable {
String key = (String) aInvocation.getArguments()[0];
return attributes.get(key);
}
});

Mockito.doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock aInvocation) throws Throwable {
String key = (String) aInvocation.getArguments()[0];
Object value = aInvocation.getArguments()[1];
attributes.put(key, value);
return null;
}
}).when(sessionObj).setAttribute(anyString(), anyObject());
}

When the attribute is set (for any keys and any values), the block inside Mockito.doAnswer() is executed.
When the attribute is got (for any keys), the block inside when() is executed.

The Answer class defines a method called answer which makes available the access of the value assigned at the object.

This value is stored afterward in the attributes map. Once the value is requested for checking, this is returned from this map.

Now you can start again the Junit test and look the success result.

The source code is available on Github. Enjoy it!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s