title: Unit testing spring mvc controller with mockito
body: <p>i'm using mockito and junit and run unit test against spring mvc
  my flow of code is:</p>
  
  <p><code>Service Layer</code> -> <code>Model Layer</code> -> <code>Controller Layer</code></p>
  
  <p>i was <strong>successfully</strong> testing the Controller against the model layer with the code:</p>
  
  <pre><code>@RunWith(MockitoJUnitRunner.class)
  public class HashLinkerControllerTest {
  
  private static final Logger LOGGER = Logger
          .getLogger(HashLinkerControllerTest.class);
  
  
  
  @Mock
  private HashLinkerModel modelMock;
  
  @InjectMocks
  private HashLinkerController controller;
  
  private MockMvc mockMvc;
  
  @Before
  public void setup() {
  
      MockitoAnnotations.initMocks(this);
      this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
  
  }
  
    @Test
  public void update() throws Exception {
      int date = 123;
      String hashToCheck = "asdfasdfasdfasdfas";
      HashLinker first = this.createHashLinker(hashToCheck, "some name",
              "some des", "some data", date);
  
      when(modelMock.update(first)).then(returnsFirstArg());
      mockMvc.perform(
              put("/api/hashService/" + hashToCheck)
                      .contentType(TestUtil.APPLICATION_JSON_UTF8)
                      .content(
                              TestUtil.convertObjectToJsonBytesWithSettersOnly(first))
                      .accept(TestUtil.APPLICATION_JSON_UTF8))
              .andExpect(status().isOk())
              .andExpect(
                      content().contentType(TestUtil.APPLICATION_JSON_UTF8))
              .andExpect(jsonPath("$.hash", is(hashToCheck)))
              .andExpect(jsonPath("$.description", is("some des")))
              .andExpect(jsonPath("$.name", is("some name")));
  
      verify(modelMock, times(1)).update(first);
      verifyNoMoreInteractions(modelMock);
  }
  </code></pre>
  
  <p>but now i'm looking for  a way to test the 3 layers structure. i.e testing the service against the controller . i came up with :</p>
  
  <pre><code>@RunWith(MockitoJUnitRunner.class)
  public class HashLinkerControllerServiceLayerTest {
  
  private static final Logger LOGGER = Logger
          .getLogger(HashLinkerControllerServiceLayerTest.class);
  
  @Mock
  private HashLinkerService serviceMock;
  
  @InjectMocks
  // @Mock
  private HashLinkerModel modelMock;
  
  private HashLinkerController controller;
  
  private MockMvc mockMvc;
  
  @Before
  public void setup() {
  
      MockitoAnnotations.initMocks(this);
      controller = new HashLinkerController(modelMock);
      this.mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
  
  }
  </code></pre>
  
  <p>and doing the test with</p>
  
  <pre><code>@Test
  public void update() throws Exception {
      int date = 123;
      String hashToCheck = "asdfasdfasdfasdfas";
      HashLinker first = this.createHashLinker(hashToCheck, "some name",
              "some des", "some data", date);
  
      when(serviceMock.update(first)).then(returnsFirstArg());
      mockMvc.perform(
              put("/api/hashService/" + hashToCheck)
                      .contentType(TestUtil.APPLICATION_JSON_UTF8)
                      .content(
                              TestUtil.convertObjectToJsonBytesWithSettersOnly(first))
                      .accept(TestUtil.APPLICATION_JSON_UTF8))
              .andExpect(status().isOk())
              .andExpect(
                      content().contentType(TestUtil.APPLICATION_JSON_UTF8))
              .andExpect(jsonPath("$.hash", is(hashToCheck)))
              .andExpect(jsonPath("$.description", is("some des")))
              .andExpect(jsonPath("$.name", is("some name")));
  
      verify(serviceMock, times(1)).update(first);
      verifyNoMoreInteractions(serviceMock);
  }
  </code></pre>
  
  <p>the test is the same as above expect i have changed <code>modelMock</code> to be <code>serviceMock</code>. for some reason this test fails . i get 404.
  any ideas?</p>
  
  <p><code>version:</code></p>
  
  <p><code>&lt;spring.core.version&gt;3.2.6.RELEASE&lt;/spring.core.version&gt;</code>
  <code>&lt;spring.test.version&gt;3.2.6.RELEASE&lt;/spring.test.version&gt;</code>
  <code>&lt;mockito.version&gt;1.9.5&lt;/mockito.version&gt;</code>
  <code>&lt;junit.version&gt;4.8.2&lt;/junit.version&gt;</code></p>
  
  <p><strong>EDIT</strong>:</p>
  
  <pre><code>@Component
  public class HashLinkerModel {
  
  private static final Logger LOGGER = Logger.getLogger(HashLinkerModel.class);
  
  HashLinkerService service;
  
  /** The unicode service. */
  UnicodeService unicodeService;
  
  @Autowired
  public HashLinkerModel(HashLinkerService service, UnicodeService unicodeService){
      this.service = service;
      this.unicodeService = unicodeService;
  
  }
  
  
  
  
       /**
   * check if hash exists before creation
   * @param toHash
   * @return
   */
  private HashLinker checkAndcreate(HashLinker toHash){
  
  
      String hash = this.createHash(toHash.getData());
      toHash.setHash(hash);
  
      LOGGER.info("add " + hash + ". this is the hash of string " + toHash.getData());
  
      /* if this hash already in system. return null. otherwise create */
      HashLinker exists =  service.findByHash(toHash.getHash());
  
      if (null != exists) 
          return exists;
  //** we use service here ** 
      return service.create(toHash);
  }
  
  public HashLinker create(HashLinker entity) {
      // TODO Auto-generated method stub
  
      RestPreconditions.checkRequestElementNotNull(entity, LOGGER);
      RestPreconditions.checkRequestElementNotNull(entity.getData(), LOGGER);
  
      String uniName = getUniHelper().unicode(entity.getName());
      String uniDesc = getUniHelper().unicode(entity.getDescription());
  
      HashLinker toHash = new HashLinker();
      toHash.setData(entity.getData());
  
      toHash.setType(entity.getType());
  
      String baseURL = entity.getBaseURL();
  
      if (null != baseURL) 
              baseURL  = (baseURL.length() &gt; HashLinker.getIntMaxBaseURL()) ? baseURL.substring(0, HashLinker.getIntMaxBaseURL()) : baseURL;
  
      toHash.setBaseURL(baseURL);
      toHash.setStatus(0);
      // update lecker's macros results
      toHash.setName(uniName);
      toHash.setDescription(uniDesc);
  
  
      return checkAndcreate(toHash);
  
  }
  </code></pre>