感谢@J Andy的思路,我意识到我一直在走这条路。在Update
1中,我试图将模拟服务注入,
MockMvc但是在退后一步后,我意识到并不是
MockMvc要测试的是,而是
PolicyController我要测试的。
为了提供一些背景知识,我想避免在Spring
MVC应用程序中对@Controllers进行传统的单元测试,因为我想测试仅通过在Spring自身内部运行控制器才能提供的功能(例如,对控制器操作的RESTful调用)。这可以通过使用Spring
MVC Test框架来实现,该框架允许您在Spring中运行测试。
您可以从代码在我最初的问题看,我是运行在一个春天MVC测试
WebApplicationContext(即
this.mockMvc =MockMvcBuilders.webAppContextSetup(this.wac).build();而我) 应该
已经做了独立运行。独立运行使我可以直接注入要测试的控制器,因此可以控制将服务注入控制器的方式(即强制使用模拟服务)。
这在代码中更容易解释。因此对于以下控制器:
import javax.validation.Valid;import name.hines.steven.medical_claims_tracker.domain.Benefit;import name.hines.steven.medical_claims_tracker.domain.Policy;import name.hines.steven.medical_claims_tracker.services.DomainEntityService;import name.hines.steven.medical_claims_tracker.services.PolicyService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.validation.BindingResult;import org.springframework.web.bind.annotation.ModelAttribute;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.ModelAndView;@Controller@RequestMapping("/policies")public class PolicyController extends DomainEntityController<Policy> { @Autowired private PolicyService service; @RequestMapping(value = "persist", method = RequestMethod.POST) public String createOrUpdate(@Valid @ModelAttribute("policy") Policy policy, BindingResult result) { if (result.hasErrors()) { return "createOrUpdatePolicyForm"; } service.save(policy); return "redirect:list"; }}现在,我具有以下测试类,其中的服务已成功被模拟出来,并且我的测试数据库不再受命:
package name.hines.steven.medical_claims_tracker.controllers;import static org.mockito.Matchers.isA;import static org.mockito.Mockito.when;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;import name.hines.steven.medical_claims_tracker.domain.Policy;import name.hines.steven.medical_claims_tracker.services.PolicyService;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.InjectMocks;import org.mockito.Mock;import org.mockito.MockitoAnnotations;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import org.springframework.test.web.servlet.MockMvc;import org.springframework.test.web.servlet.setup.MockMvcBuilders;@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration({ "classpath:/applicationContext.xml" })public class PolicyControllerTest { @Mock PolicyService policyService; @InjectMocks PolicyController controllerUnderTest; private MockMvc mockMvc; @Before public void setup() { // this must be called for the @Mock annotations above to be processed // and for the mock service to be injected into the controller under // test. MockitoAnnotations.initMocks(this); this.mockMvc = MockMvcBuilders.standaloneSetup(controllerUnderTest).build(); } @Test public void createOrUpdateFailsWhenInvalidDataPostedAndSendsUserBackToForm() throws Exception { // POST no data to the form (i.e. an invalid POST) mockMvc.perform(post("/policies/persist")).andExpect(status().isOk()) .andExpect(model().attributeHasErrors("policy")) .andExpect(view().name("createOrUpdatePolicy")); } @Test public void createOrUpdateSuccessful() throws Exception { when(policyService.save(isA(Policy.class))).thenReturn(new Policy()); mockMvc.perform( post("/policies/persist").param("companyName", "Company Name") .param("name", "Name").param("effectiveDate", "2001-01-01")) .andExpect(status().isMovedTemporarily()).andExpect(model().hasNoErrors()) .andExpect(redirectedUrl("list")); }}关于Spring方面,我仍然非常学习,因此欢迎任何可以改善我的解释的评论很有帮助。



