I am new to jMockIt and so wanted to learn it. I thought of implementing a synonym servlet kata. The servlet takes a word as input and returns the synoyms of the words as a comma seperated string. The objective of the kata that I implemented was:
- Learning jMockIt stubbing and mocking features.
- Choosing between stubbing and mocking based on the situation.
- Implementing readable, maintainable and trustworthy unit tests.
I request code reviewers to provide feedback in above mentioned areas. I am open to receive feedback about the servlet code as well. The code is below:
class SynonymServlet extends HttpServlet {
public SynonymServlet(RecentCache cache, SynonymProvider provider) {
this.cache = cache;
this.provider = provider;
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//input processing
String word = getInputWordFromURL(request.getRequestURI());
//cache management
List<String> synonyms = cache.get(word);
if (synonyms == null) {
synonyms = provider.getSynonyms(word);
cache.put(word, synonyms);
}
//response creation
String responseString = StringUtils.join(synonyms, ", ");
response.getOutputStream().print(responseString);
}
private static String getInputWordFromURL(String URL) {
String[] tokenizedURL = URL.split("/");
String word = tokenizedURL[tokenizedURL.length - 1];
return word;
}
private RecentCache cache;
private SynonymProvider provider;
}
interface RecentCache {
List<String> get(String word);
void put(String word, List<String> synonyms);
}
interface SynonymProvider {
List<String> getSynonyms(String word);
}
public class SynonymServletTest {
@Mocked
RecentCache cache;
@Mocked
SynonymProvider provider;
@Test
public void should_always_look_into_cache_first() throws ServletException, IOException {
//Mock
new Expectations() {
{
cache.get("reputation");
times = 1;
}
};
SynonymServlet servlet = new SynonymServlet(cache, provider);
servlet.doGet(getRequest("/synonyms/reputation"), new MockHttpServletResponse());
}
@Test
public void should_return_from_cache_when_found() throws Exception, IOException {
//Stub
new Expectations() {
{
cache.get("reputation");
result = new ArrayList<String>() {{
add("credit");
add("reputation");
}};
}
};
MockHttpServletResponse response = new MockHttpServletResponse();
SynonymServlet servlet = new SynonymServlet(cache, provider);
servlet.doGet(getRequest("/synonyms/reputation"), response);
assertThat(response.getContentAsString()).isEqualTo("credit, reputation");
}
@Test
public void should_get_it_from_provider_when_not_found_in_cache() throws ServletException, IOException {
//Stub
new NonStrictExpectations()
{
{
cache.get("reputation");
result = null;
}
};
//Mock
new Expectations() {
{
provider.getSynonyms("reputation");
times = 1;
}
};
SynonymServlet servlet = new SynonymServlet(cache, provider);
servlet.doGet(getRequest("/synonyms/reputation"), new MockHttpServletResponse());
}
@Test
public void should_return_the_same_as_provided_by_provider() throws ServletException, IOException {
//Stub
new NonStrictExpectations() {
{
cache.get("reputation");
result = null;
}
};
new Expectations() {
{
provider.getSynonyms("reputation");
times = 1;
result = new ArrayList<String>() {{
add("credit");
add("reputation");
}};
}
};
SynonymServlet servlet = new SynonymServlet(cache, provider);
MockHttpServletResponse response = new MockHttpServletResponse();
servlet.doGet(getRequest("/synonyms/reputation"), response);
assertThat(response.getContentAsString()).isEqualTo("credit, reputation");
}
@Test
public void should_update_cache_when_not_in_cache() throws ServletException, IOException {
//Stub
new Expectations() {
{
cache.get("reputation");
result = null;
}
};
//Stub
new Expectations() {
{
provider.getSynonyms("reputation");
result = new ArrayList<String>() {{
add("credit");
add("reputation");
}};
}
};
//Mock
new Expectations() {
{
cache.put("reputation", (List<String>) any);
times = 1;
}
};
SynonymServlet servlet = new SynonymServlet(cache, provider);
servlet.doGet(getRequest("/synonyms/reputation"), new MockHttpServletResponse());
}
private MockHttpServletRequest getRequest(String url) {
return new MockHttpServletRequestBuilder()
.withURL(url)
.build();
}
}