使用Spring,@ InjectMock注释的测试目标不使用模拟

时间:2014-01-27 10:25:39

标签: java spring unit-testing spring-mvc mockito

我正在尝试对Spring 4.0.0 MVC应用程序进行单元测试。

我的控制器定义如下:

@Controller
@RequestMapping("/test")
public class TestCtrl {
    @Autowired
    private TestService testService;

    @Autowired
    private TestRessourceAssembler testRessourceAssembler;

    @Autowired
    private ResponseComposer responseComposer;

    @RequestMapping(value = "", method = RequestMethod.GET,produces = "application/json")
    public HttpEntity showAll(Pageable pageable) {   
        Page<Test> patr = testService.getAll(pageable);
        return responseComposer.composePage(patr,testRessourceAssembler);
    }

    @RequestMapping(value = "/{name}", method = RequestMethod.GET)
    public HttpEntity<TestRessource> show(@PathVariable String name) {
        Test test = testService.getOne(name);
        if(test == null){
            return new ResponseEntity("Erreur !",HttpStatus.NOT_FOUND);
        }
        return responseComposer.compose(test,testRessourceAssembler);
    }
}

我的控制器单元测试如下:

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
@WebAppConfiguration
@ContextConfiguration(classes = {ApplicationConfig.class, TestMongoConfig.class, RestConfig.class, WebMvcConfig.class})
public class TestCtrlTests{

    @InjectMocks
    TestCtrl testCtrl;

    @Mock
    TestService testService;

    @Autowired
    protected WebApplicationContext wac;

    protected MockMvc mockMvc;

    @Before
    public void setup(){
        MockitoAnnotations.initMocks(this);

        when(testService.getOne("jexiste")).thenReturn(new com.thalesgroup.ito.c2s.mc.portail.test.domain.Test("jexiste",1990));
        when(testService.getOne("plaf")).thenReturn(null);

        this.mockMvc = webAppContextSetup(this.wac).build();
       }

    @Test
    public void simpleGetAnswer() throws Exception{
        assertNotNull(mockMvc);
        mockMvc.perform(get("/test")).andExpect(status().isOk());
        mockMvc.perform(get("/test/jexiste")).andExpect(status().isOk());
        mockMvc.perform(get("/test/plaf")).andExpect(status().isNotFound());
    }
}

当我运行测试时,注入并使用“普通”TestService bean(我可以在日志中看到跟踪),而不是模拟。

所以我在互联网上阅读了一些内容并替换了

this.mockMvc = webAppContextSetup(this.wac).build();

this.mockMvc = standaloneSetup(TestCtrl.class).build();

但是,我知道会发生这种情况,在执行此操作时我没有更多的Spring上下文,因此我的PageableArgumentResolver和我的其他bean(testRessourceAssembler,responseComposer)不再被注入...所以它们是Null并且发生了的NullPointerException。

我的问题是:

1)我是在设计错误的东西?

2)如果没有,我怎样才能在我的控制器中注入模拟,同时保持其他bean不受上下文的影响?

谢谢你!

1 个答案:

答案 0 :(得分:5)

我调查了你的测试,这应该有效。只需使用模拟bean在控制器上构建MockMvc即可。在此之后,所有的模拟都将在测试中可见。

  

接受@Controller注册的MockMvcBuilder,从而允许完全控制实例化和控制器及其依赖关系的初始化,类似于普通单元测试,并且还可以测试一个控制器

不要使用Spring Integration测试!这是简单的单元测试!

修正测试

@RunWith(MockitoJUnitRunner.class)
public class TestCtrlTests{

    @InjectMocks
    TestCtrl testCtrl;

    @Mock
    TestService testService;

    protected MockMvc mockMvc;

    @Before
    public void setup(){
        when(testService.getOne("jexiste")).thenReturn(new com.thalesgroup.ito.c2s.mc.portail.test.domain.Test("jexiste",1990));
        when(testService.getOne("plaf")).thenReturn(null);

        this.mockMvc = standaloneSetup(testCtrl).build();
    }

    @Test
    public void simpleGetAnswer() throws Exception{
        assertNotNull(mockMvc);
        mockMvc.perform(get("/test")).andExpect(status().isOk());
        mockMvc.perform(get("/test/jexiste")).andExpect(status().isOk());
        mockMvc.perform(get("/test/plaf")).andExpect(status().isNotFound());
    }
}