带有Mockito的单元测试Spring MVC控制器 [英] Unit testing spring mvc controller with mockito

查看:144
本文介绍了带有Mockito的单元测试Spring MVC控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Mockito和Junit并针对Spring MVC运行单元测试 我的代码流是:

i'm using mockito and junit and run unit test against spring mvc my flow of code is:

Service Layer-> Model Layer-> Controller Layer

成功使用以下代码针对模型层对Controller进行了测试:

i was successfully testing the Controller against the model layer with the 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);
}

但是现在我正在寻找一种测试3层结构的方法.即针对控制器测试服务.我想出了:

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 :

@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. 有什么想法吗?

the test is the same as above expect i have changed modelMock to be serviceMock. for some reason this test fails . i get 404. any ideas?

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>

编辑:

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

}

推荐答案

放行

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

但在模拟Mvc断言之前,以验证是否使用了您的模拟.

but before mockMvc assertions, to verify that your mock is used.

您的代码的一般问题:

  • 使用注释@RunWith(MockitoJUnitRunner.class)无需手动初始化Mockito.

  • With annotation @RunWith(MockitoJUnitRunner.class) initializing Mockito manually is not necessary.

@MockitoJUnitRunner

初始化带有Mock注释的模拟,因此不需要显式使用 MockitoAnnotations.initMocks(Object).

Initializes mocks annotated with Mock, so that explicit usage of MockitoAnnotations.initMocks(Object) is not necessary.

  • 单元测试

  • Unit testing

    我正在寻找一种测试三层结构的方法.

    i'm looking for a way to test the 3 layers structure.

    当测试涉及三层时,该测试是集成测试.

    When three layers are involved in the test, the test is an integration test.

    在单元测试中,最好有许多小的方法来测试不同的行为.因此,一种方法应该测试HTTP响应,第二种方法应该验证是否调用了服务.

    In unit testing it is better to have many small method for testing different behaviour. So one method should test HTTP Response, second should verify if service is invoked.

    这篇关于带有Mockito的单元测试Spring MVC控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆