2014-01-19 3 views
2

Я использую Mockito и JUnit и запустить модульный тест на Spring MVC мой поток кода:блок тестирования Spring MVC контроллер с Mockito

Service Layer ->Model Layer ->Controller Layer

я был успешно тестирование контроллера на уровне модели с кодом:

@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); 
} 

но теперь я ищу способ проверить на 3 слоя состав. i.e тестирование службы против контроллера. я придумал:

@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(); 

} 

и делать тест с

@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); 
} 

тест такой же, как и выше ожидать я изменил modelMock быть serviceMock. по какой-то причине этот тест терпит неудачу. я получаю 404. любые идеи?

version:

<spring.core.version>3.2.6.RELEASE</spring.core.version> <spring.test.version>3.2.6.RELEASE</spring.test.version> <mockito.version>1.9.5</mockito.version> <junit.version>4.8.2</junit.version>

EDIT:

@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() > 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); 

} 
+0

Покажите нам, как 'HashLinkerModel' использует' HashLinkerService.update (первый) ' – MariuszS

+0

@MariuszS я добавил соответствующий код hashLinkerModel. спасибо – oak

+0

Спасибо, но в этом коде 'HashLinkerService.update (first)' никогда не выполняется, может быть, это проблема. Также 'modelMock.update (first)' здесь не отображается, похоже, что этот код не связан с модульным тестом. Покажите мне свой метод 'update()'. – MariuszS

ответ

0

кладете линии

verify(serviceMock, times(1)).update(first); 

после

mockMvc.perform(
     put("/api/hashService/" + hashToCheck) 
       .contentType(TestUtil.APPLICATION_JSON_UTF8) 
       .content(
         TestUtil.convertObjectToJsonBytesWithSettersOnly(first)) 
       .accept(TestUtil.APPLICATION_JSON_UTF8)); 

, но до mockMvc утверждений, чтобы убедиться, что используется ваш макет.

Общие проблемы с вашим кодом:

  • С аннотацией @RunWith(MockitoJUnitRunner.class) инициализации Mockito вручную не нужно.

    @MockitoJUnitRunner

    Инициализация Mocks аннотируются Mock, так что явное использование MockitoAnnotations.initMocks (Object) не является необходимым.

  • Юнит

    Я ищу способ проверить структуру 3 слоев.

    Когда три слоя участвуют в тесте, тест тест интеграции.

  • В модульном тестировании лучше иметь много небольших методов для тестирования различного поведения. Таким образом, один метод должен проверять HTTP-ответ, второй должен проверить, вызвана ли служба.

+0

спасибо за советы. попробовал поставить инструкцию 'verify' после выполнения. услуга не вызвана. infact я получаю ошибку 404. что означает что-то с контроллером не работает должным образом, не так ли? возможно, моя структура 3-го уровня для того, как начать тест, не допускается с весной? – oak

+0

@oak Нам нужно больше данных, Покажите нам 'HashLinkerModel' и' HashLinkerService' – MariuszS

Смежные вопросы