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

plu*_*uce 3 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

@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());
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

this.mockMvc = webAppContextSetup(this.wac).build();
Run Code Online (Sandbox Code Playgroud)

this.mockMvc = standaloneSetup(TestCtrl.class).build();
Run Code Online (Sandbox Code Playgroud)

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

我的问题是:

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

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

谢谢你 !

Mar*_*szS 5

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

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

不要使用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());
    }
}
Run Code Online (Sandbox Code Playgroud)