感谢@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"; } }
@H_404_23@现在,我具有以下测试类,其中的服务已成功被模拟出来,并且我的测试数据库不再受命:
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")); } }
@H_404_23@关于Spring方面,我仍然非常学习,因此欢迎任何可以改善我的解释的评论很有帮助。
解决方法
我有一个Spring 3.2 MVC应用程序,并且正在使用Spring MVC测试框架来测试控制器操作上的GET和POST请求。我正在使用Mockito模拟服务,但是发现模拟被忽略并且正在使用我的实际服务层(因此,数据库被命中)。
我的Controller测试中的代码:
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.Mock; import org.mockito.MockitoAnnotations; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration({ "classpath:/applicationContext.xml","classpath:/tests_persistence-applicationContext.xml" }) public class PolicyControllerTest { @Mock PolicyService service; @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); // this must be called for the @Mock annotations above to be processed. MockitoAnnotations.initMocks(this); } @Test public void createOrUpdateFailsWhenInvalidDataPostedAndSendsUserBackToForm() throws Exception { // Post no parameters in this request to force errors mockMvc.perform(post("/policies/persist")).andExpect(status().isOk()) .andExpect(model().attributeHasErrors("policy")) .andExpect(view().name("createOrUpdatePolicy")); } @Test public void createOrUpdateSuccessful() throws Exception { // Mock the service method to force a known response when(service.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")); } }
你会注意到我有两个上下文配置文件;这是一个黑客,因为如果我无法阻止控制器测试到达实际的服务层,则该服务层也可能会将其存储库指向测试数据库。我已经到了无法再摆脱这种黑客攻击的地步,需要能够正确地模拟我的服务层。
为什么在
when(service.save(isA(Policy.class))).thenReturn(new Policy());PolicyService
中不加入并模拟出save方法?我是否在某处缺少某些Mockito配置?我需要在Spring配置中添加一些内容吗?到目前为止,我的研究仅限于谷歌搜索“ spring mvc test Mockito不起作用”,但这并没有给我带来太多帮助。谢谢。
更新1
你是正确的@ tom-verelst
,我指的是PolicyService service
;测试中的那行,因此,MockMvc遗嘱中的服务当然已由Spring注入。然后,我尝试标注
private MockMvc mockMvc
有@InjectMocks
和仍然得到了同样的问题(即内部的服务MockMvc是不是因为我是期待它是嘲笑)。我已经在调试过程PolicyServiceImpl
中调用上的save方法的位置添加了堆栈跟踪(这与模拟服务中对save方法的期望调用相反)。Thread [main] (Suspended (breakpoint at line 29 in DomainEntityServiceImpl) PolicyServiceImpl(DomainEntityServiceImpl<T>).save(T) line: 29 NativeMethodAccessorImpl.invoke0(Method,Object,Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object,Object[]) line: 39 DelegatingMethodAccessorImpl.invoke(Object,Object[]) line: 25 Method.invoke(Object,Object...) line: 597 AopUtils.invokeJoinpointUsingReflection(Object,Method,Object[]) line: 317 ReflectiveMethodInvocation.invokeJoinpoint() line: 183 ReflectiveMethodInvocation.proceed() line: 150 TransactionInterceptor$1.proceedWithInvocation() line: 96 TransactionInterceptor(TransactionAspectSupport).invokeWithinTransaction(Method,Class,TransactionAspectSupport$InvocationCallback) line: 260 TransactionInterceptor.invoke(MethodInvocation) line: 94 ReflectiveMethodInvocation.proceed() line: 172 JdkDynamicAopProxy.invoke(Object,Object[]) line: 204 $Proxy44.save(DomainEntity) line: not available PolicyController.createOrUpdate(Policy,BindingResult) line: 64 NativeMethodAccessorImpl.invoke0(Method,Object...) line: 597 ServletInvocableHandlerMethod(InvocableHandlerMethod).invoke(Object...) line: 219 ServletInvocableHandlerMethod(InvocableHandlerMethod).invokeForRequest(NativeWebRequest,ModelAndViewContainer,Object...) line: 132 ServletInvocableHandlerMethod.invokeAndHandle(ServletWebRequest,Object...) line: 104 RequestMappingHandlerAdapter.invokeHandleMethod(HttpServletRequest,HttpServletResponse,HandlerMethod) line: 746 RequestMappingHandlerAdapter.handleInternal(HttpServletRequest,HandlerMethod) line: 687 RequestMappingHandlerAdapter(AbstractHandlerMethodAdapter).handle(HttpServletRequest,Object) line: 80 TestDispatcherServlet(DispatcherServlet).doDispatch(HttpServletRequest,HttpServletResponse) line: 925 TestDispatcherServlet(DispatcherServlet).doService(HttpServletRequest,HttpServletResponse) line: 856 TestDispatcherServlet(FrameworkServlet).processRequest(HttpServletRequest,HttpServletResponse) line: 915 TestDispatcherServlet(FrameworkServlet).doPost(HttpServletRequest,HttpServletResponse) line: 822 TestDispatcherServlet(HttpServlet).service(HttpServletRequest,HttpServletResponse) line: 727 TestDispatcherServlet(FrameworkServlet).service(HttpServletRequest,HttpServletResponse) line: 796 TestDispatcherServlet.service(HttpServletRequest,HttpServletResponse) line: 66 TestDispatcherServlet(HttpServlet).service(ServletRequest,ServletResponse) line: 820 MockFilterChain$ServletFilterProxy.doFilter(ServletRequest,ServletResponse,FilterChain) line: 168 MockFilterChain.doFilter(ServletRequest,ServletResponse) line: 136 MockMvc.perform(RequestBuilder) line: 134 PolicyControllerTest.createOrUpdateSuccessful() line: 67 NativeMethodAccessorImpl.invoke0(Method,Object...) line: 597 FrameworkMethod$1.runReflectiveCall() line: 44 FrameworkMethod$1(ReflectiveCallable).run() line: 15 FrameworkMethod.invokeExplosively(Object,Object...) line: 41 InvokeMethod.evaluate() line: 20 RunBefores.evaluate() line: 28 RunBeforeTestMethodCallbacks.evaluate() line: 74 RunAfterTestMethodCallbacks.evaluate() line: 83 SpringRepeat.evaluate() line: 72 SpringJUnit4ClassRunner.runChild(FrameworkMethod,RunNotifier) line: 231 SpringJUnit4ClassRunner.runChild(Object,RunNotifier) line: 88 ParentRunner$3.run() line: 193 ParentRunner$1.schedule(Runnable) line: 52 SpringJUnit4ClassRunner(ParentRunner<T>).runChildren(RunNotifier) line: 191 ParentRunner<T>.access$000(ParentRunner,RunNotifier) line: 42 ParentRunner$2.evaluate() line: 184 RunBeforeTestClassCallbacks.evaluate() line: 61 RunAfterTestClassCallbacks.evaluate() line: 71 SpringJUnit4ClassRunner(ParentRunner<T>).run(RunNotifier) line: 236 SpringJUnit4ClassRunner.run(RunNotifier) line: 174 JUnit4TestMethodReference(JUnit4TestReference).run(TestExecution) line: 50 TestExecution.run(ITestReference[]) line: 38 RemoteTestRunner.runTests(String[],String,TestExecution) line: 467 RemoteTestRunner.runTests(TestExecution) line: 683 RemoteTestRunner.run() line: 390 RemoteTestRunner.main(String[]) line: 197
进一步的研究(使用@Mock时将Mockito注入Null值到Spring bean中?)建议在测试中将其
@InjectMocks
应用于PolicyController
成员变量,但是正如第一个链接中的一个答案所指出的那样,此操作无济于事,因为Spring没有一无所知。
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")); } }
@H_404_23@关于Spring方面,我仍然非常学习,因此欢迎任何可以改善我的解释的评论很有帮助。
解决方法
我有一个Spring 3.2 MVC应用程序,并且正在使用Spring MVC测试框架来测试控制器操作上的GET和POST请求。我正在使用Mockito模拟服务,但是发现模拟被忽略并且正在使用我的实际服务层(因此,数据库被命中)。
我的Controller测试中的代码:
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.Mock; import org.mockito.MockitoAnnotations; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration({ "classpath:/applicationContext.xml","classpath:/tests_persistence-applicationContext.xml" }) public class PolicyControllerTest { @Mock PolicyService service; @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); // this must be called for the @Mock annotations above to be processed. MockitoAnnotations.initMocks(this); } @Test public void createOrUpdateFailsWhenInvalidDataPostedAndSendsUserBackToForm() throws Exception { // Post no parameters in this request to force errors mockMvc.perform(post("/policies/persist")).andExpect(status().isOk()) .andExpect(model().attributeHasErrors("policy")) .andExpect(view().name("createOrUpdatePolicy")); } @Test public void createOrUpdateSuccessful() throws Exception { // Mock the service method to force a known response when(service.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")); } }
你会注意到我有两个上下文配置文件;这是一个黑客,因为如果我无法阻止控制器测试到达实际的服务层,则该服务层也可能会将其存储库指向测试数据库。我已经到了无法再摆脱这种黑客攻击的地步,需要能够正确地模拟我的服务层。
为什么在
when(service.save(isA(Policy.class))).thenReturn(new Policy());PolicyService
中不加入并模拟出save方法?我是否在某处缺少某些Mockito配置?我需要在Spring配置中添加一些内容吗?到目前为止,我的研究仅限于谷歌搜索“ spring mvc test Mockito不起作用”,但这并没有给我带来太多帮助。谢谢。
更新1
你是正确的@ tom-verelst
,我指的是PolicyService service
;测试中的那行,因此,MockMvc遗嘱中的服务当然已由Spring注入。然后,我尝试标注
private MockMvc mockMvc
有@InjectMocks
和仍然得到了同样的问题(即内部的服务MockMvc是不是因为我是期待它是嘲笑)。我已经在调试过程PolicyServiceImpl
中调用上的save方法的位置添加了堆栈跟踪(这与模拟服务中对save方法的期望调用相反)。Thread [main] (Suspended (breakpoint at line 29 in DomainEntityServiceImpl) PolicyServiceImpl(DomainEntityServiceImpl<T>).save(T) line: 29 NativeMethodAccessorImpl.invoke0(Method,Object,Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object,Object[]) line: 39 DelegatingMethodAccessorImpl.invoke(Object,Object[]) line: 25 Method.invoke(Object,Object...) line: 597 AopUtils.invokeJoinpointUsingReflection(Object,Method,Object[]) line: 317 ReflectiveMethodInvocation.invokeJoinpoint() line: 183 ReflectiveMethodInvocation.proceed() line: 150 TransactionInterceptor$1.proceedWithInvocation() line: 96 TransactionInterceptor(TransactionAspectSupport).invokeWithinTransaction(Method,Class,TransactionAspectSupport$InvocationCallback) line: 260 TransactionInterceptor.invoke(MethodInvocation) line: 94 ReflectiveMethodInvocation.proceed() line: 172 JdkDynamicAopProxy.invoke(Object,Object[]) line: 204 $Proxy44.save(DomainEntity) line: not available PolicyController.createOrUpdate(Policy,BindingResult) line: 64 NativeMethodAccessorImpl.invoke0(Method,Object...) line: 597 ServletInvocableHandlerMethod(InvocableHandlerMethod).invoke(Object...) line: 219 ServletInvocableHandlerMethod(InvocableHandlerMethod).invokeForRequest(NativeWebRequest,ModelAndViewContainer,Object...) line: 132 ServletInvocableHandlerMethod.invokeAndHandle(ServletWebRequest,Object...) line: 104 RequestMappingHandlerAdapter.invokeHandleMethod(HttpServletRequest,HttpServletResponse,HandlerMethod) line: 746 RequestMappingHandlerAdapter.handleInternal(HttpServletRequest,HandlerMethod) line: 687 RequestMappingHandlerAdapter(AbstractHandlerMethodAdapter).handle(HttpServletRequest,Object) line: 80 TestDispatcherServlet(DispatcherServlet).doDispatch(HttpServletRequest,HttpServletResponse) line: 925 TestDispatcherServlet(DispatcherServlet).doService(HttpServletRequest,HttpServletResponse) line: 856 TestDispatcherServlet(FrameworkServlet).processRequest(HttpServletRequest,HttpServletResponse) line: 915 TestDispatcherServlet(FrameworkServlet).doPost(HttpServletRequest,HttpServletResponse) line: 822 TestDispatcherServlet(HttpServlet).service(HttpServletRequest,HttpServletResponse) line: 727 TestDispatcherServlet(FrameworkServlet).service(HttpServletRequest,HttpServletResponse) line: 796 TestDispatcherServlet.service(HttpServletRequest,HttpServletResponse) line: 66 TestDispatcherServlet(HttpServlet).service(ServletRequest,ServletResponse) line: 820 MockFilterChain$ServletFilterProxy.doFilter(ServletRequest,ServletResponse,FilterChain) line: 168 MockFilterChain.doFilter(ServletRequest,ServletResponse) line: 136 MockMvc.perform(RequestBuilder) line: 134 PolicyControllerTest.createOrUpdateSuccessful() line: 67 NativeMethodAccessorImpl.invoke0(Method,Object...) line: 597 FrameworkMethod$1.runReflectiveCall() line: 44 FrameworkMethod$1(ReflectiveCallable).run() line: 15 FrameworkMethod.invokeExplosively(Object,Object...) line: 41 InvokeMethod.evaluate() line: 20 RunBefores.evaluate() line: 28 RunBeforeTestMethodCallbacks.evaluate() line: 74 RunAfterTestMethodCallbacks.evaluate() line: 83 SpringRepeat.evaluate() line: 72 SpringJUnit4ClassRunner.runChild(FrameworkMethod,RunNotifier) line: 231 SpringJUnit4ClassRunner.runChild(Object,RunNotifier) line: 88 ParentRunner$3.run() line: 193 ParentRunner$1.schedule(Runnable) line: 52 SpringJUnit4ClassRunner(ParentRunner<T>).runChildren(RunNotifier) line: 191 ParentRunner<T>.access$000(ParentRunner,RunNotifier) line: 42 ParentRunner$2.evaluate() line: 184 RunBeforeTestClassCallbacks.evaluate() line: 61 RunAfterTestClassCallbacks.evaluate() line: 71 SpringJUnit4ClassRunner(ParentRunner<T>).run(RunNotifier) line: 236 SpringJUnit4ClassRunner.run(RunNotifier) line: 174 JUnit4TestMethodReference(JUnit4TestReference).run(TestExecution) line: 50 TestExecution.run(ITestReference[]) line: 38 RemoteTestRunner.runTests(String[],String,TestExecution) line: 467 RemoteTestRunner.runTests(TestExecution) line: 683 RemoteTestRunner.run() line: 390 RemoteTestRunner.main(String[]) line: 197
进一步的研究(使用@Mock时将Mockito注入Null值到Spring bean中?)建议在测试中将其
@InjectMocks
应用于PolicyController
成员变量,但是正如第一个链接中的一个答案所指出的那样,此操作无济于事,因为Spring没有一无所知。
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.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({ "classpath:/applicationContext.xml","classpath:/tests_persistence-applicationContext.xml" })
public class PolicyControllerTest {
@Mock
PolicyService service;
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
// this must be called for the @Mock annotations above to be processed.
MockitoAnnotations.initMocks(this);
}
@Test
public void createOrUpdateFailsWhenInvalidDataPostedAndSendsUserBackToForm() throws Exception {
// Post no parameters in this request to force errors
mockMvc.perform(post("/policies/persist")).andExpect(status().isOk())
.andExpect(model().attributeHasErrors("policy"))
.andExpect(view().name("createOrUpdatePolicy"));
}
@Test
public void createOrUpdateSuccessful() throws Exception {
// Mock the service method to force a known response
when(service.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"));
}
}
Thread [main] (Suspended (breakpoint at line 29 in DomainEntityServiceImpl) PolicyServiceImpl(DomainEntityServiceImpl<T>).save(T) line: 29
NativeMethodAccessorImpl.invoke0(Method,Object,Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object,Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object,Object[]) line: 25
Method.invoke(Object,Object...) line: 597
AopUtils.invokeJoinpointUsingReflection(Object,Method,Object[]) line: 317
ReflectiveMethodInvocation.invokeJoinpoint() line: 183
ReflectiveMethodInvocation.proceed() line: 150
TransactionInterceptor$1.proceedWithInvocation() line: 96
TransactionInterceptor(TransactionAspectSupport).invokeWithinTransaction(Method,Class,TransactionAspectSupport$InvocationCallback) line: 260
TransactionInterceptor.invoke(MethodInvocation) line: 94
ReflectiveMethodInvocation.proceed() line: 172
JdkDynamicAopProxy.invoke(Object,Object[]) line: 204
$Proxy44.save(DomainEntity) line: not available
PolicyController.createOrUpdate(Policy,BindingResult) line: 64
NativeMethodAccessorImpl.invoke0(Method,Object...) line: 597
ServletInvocableHandlerMethod(InvocableHandlerMethod).invoke(Object...) line: 219
ServletInvocableHandlerMethod(InvocableHandlerMethod).invokeForRequest(NativeWebRequest,ModelAndViewContainer,Object...) line: 132
ServletInvocableHandlerMethod.invokeAndHandle(ServletWebRequest,Object...) line: 104
RequestMappingHandlerAdapter.invokeHandleMethod(HttpServletRequest,HttpServletResponse,HandlerMethod) line: 746
RequestMappingHandlerAdapter.handleInternal(HttpServletRequest,HandlerMethod) line: 687
RequestMappingHandlerAdapter(AbstractHandlerMethodAdapter).handle(HttpServletRequest,Object) line: 80
TestDispatcherServlet(DispatcherServlet).doDispatch(HttpServletRequest,HttpServletResponse) line: 925
TestDispatcherServlet(DispatcherServlet).doService(HttpServletRequest,HttpServletResponse) line: 856
TestDispatcherServlet(FrameworkServlet).processRequest(HttpServletRequest,HttpServletResponse) line: 915
TestDispatcherServlet(FrameworkServlet).doPost(HttpServletRequest,HttpServletResponse) line: 822
TestDispatcherServlet(HttpServlet).service(HttpServletRequest,HttpServletResponse) line: 727
TestDispatcherServlet(FrameworkServlet).service(HttpServletRequest,HttpServletResponse) line: 796
TestDispatcherServlet.service(HttpServletRequest,HttpServletResponse) line: 66
TestDispatcherServlet(HttpServlet).service(ServletRequest,ServletResponse) line: 820
MockFilterChain$ServletFilterProxy.doFilter(ServletRequest,ServletResponse,FilterChain) line: 168
MockFilterChain.doFilter(ServletRequest,ServletResponse) line: 136
MockMvc.perform(RequestBuilder) line: 134
PolicyControllerTest.createOrUpdateSuccessful() line: 67
NativeMethodAccessorImpl.invoke0(Method,Object...) line: 597
FrameworkMethod$1.runReflectiveCall() line: 44
FrameworkMethod$1(ReflectiveCallable).run() line: 15
FrameworkMethod.invokeExplosively(Object,Object...) line: 41
InvokeMethod.evaluate() line: 20
RunBefores.evaluate() line: 28
RunBeforeTestMethodCallbacks.evaluate() line: 74
RunAfterTestMethodCallbacks.evaluate() line: 83
SpringRepeat.evaluate() line: 72
SpringJUnit4ClassRunner.runChild(FrameworkMethod,RunNotifier) line: 231
SpringJUnit4ClassRunner.runChild(Object,RunNotifier) line: 88
ParentRunner$3.run() line: 193
ParentRunner$1.schedule(Runnable) line: 52
SpringJUnit4ClassRunner(ParentRunner<T>).runChildren(RunNotifier) line: 191
ParentRunner<T>.access$000(ParentRunner,RunNotifier) line: 42
ParentRunner$2.evaluate() line: 184
RunBeforeTestClassCallbacks.evaluate() line: 61
RunAfterTestClassCallbacks.evaluate() line: 71
SpringJUnit4ClassRunner(ParentRunner<T>).run(RunNotifier) line: 236
SpringJUnit4ClassRunner.run(RunNotifier) line: 174
JUnit4TestMethodReference(JUnit4TestReference).run(TestExecution) line: 50
TestExecution.run(ITestReference[]) line: 38
RemoteTestRunner.runTests(String[],String,TestExecution) line: 467
RemoteTestRunner.runTests(TestExecution) line: 683
RemoteTestRunner.run() line: 390
RemoteTestRunner.main(String[]) line: 197
现在,我具有以下测试类,其中的服务已成功被模拟出来,并且我的测试数据库不再受命:
关于Spring方面,我仍然非常学习,因此欢迎任何可以改善我的解释的评论很有帮助。
我有一个Spring 3.2 MVC应用程序,并且正在使用Spring MVC测试框架来测试控制器操作上的GET和POST请求。我正在使用Mockito模拟服务,但是发现模拟被忽略并且正在使用我的实际服务层(因此,数据库被命中)。
我的Controller测试中的代码:
你会注意到我有两个上下文配置文件;这是一个黑客,因为如果我无法阻止控制器测试到达实际的服务层,则该服务层也可能会将其存储库指向测试数据库。我已经到了无法再摆脱这种黑客攻击的地步,需要能够正确地模拟我的服务层。
为什么在when(service.save(isA(Policy.class))).thenReturn(new Policy());PolicyService
中不加入并模拟出save方法?我是否在某处缺少某些Mockito配置?我需要在Spring配置中添加一些内容吗?到目前为止,我的研究仅限于谷歌搜索“ spring mvc test Mockito不起作用”,但这并没有给我带来太多帮助。
谢谢。
更新1
你是正确的@ tom-verelst
,我指的是PolicyService service
;测试中的那行,因此,MockMvc遗嘱中的服务当然已由Spring注入。
然后,我尝试标注private MockMvc mockMvc
有@InjectMocks
和仍然得到了同样的问题(即内部的服务MockMvc是不是因为我是期待它是嘲笑)。我已经在调试过程PolicyServiceImpl
中调用上的save方法的位置添加了堆栈跟踪(这与模拟服务中对save方法的期望调用相反)。
进一步的研究(使用@Mock时将Mockito注入Null值到Spring bean中?)建议在测试中将其@InjectMocks
应用于PolicyController
成员变量,但是正如第一个链接中的一个答案所指出的那样,此操作无济于事,因为Spring没有一无所知。
现在,我具有以下测试类,其中的服务已成功被模拟出来,并且我的测试数据库不再受命:
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")); } }
@H_404_23@关于Spring方面,我仍然非常学习,因此欢迎任何可以改善我的解释的评论很有帮助。
解决方法
我有一个Spring 3.2 MVC应用程序,并且正在使用Spring MVC测试框架来测试控制器操作上的GET和POST请求。我正在使用Mockito模拟服务,但是发现模拟被忽略并且正在使用我的实际服务层(因此,数据库被命中)。
我的Controller测试中的代码:
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.Mock; import org.mockito.MockitoAnnotations; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration({ "classpath:/applicationContext.xml","classpath:/tests_persistence-applicationContext.xml" }) public class PolicyControllerTest { @Mock PolicyService service; @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); // this must be called for the @Mock annotations above to be processed. MockitoAnnotations.initMocks(this); } @Test public void createOrUpdateFailsWhenInvalidDataPostedAndSendsUserBackToForm() throws Exception { // Post no parameters in this request to force errors mockMvc.perform(post("/policies/persist")).andExpect(status().isOk()) .andExpect(model().attributeHasErrors("policy")) .andExpect(view().name("createOrUpdatePolicy")); } @Test public void createOrUpdateSuccessful() throws Exception { // Mock the service method to force a known response when(service.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")); } }
你会注意到我有两个上下文配置文件;这是一个黑客,因为如果我无法阻止控制器测试到达实际的服务层,则该服务层也可能会将其存储库指向测试数据库。我已经到了无法再摆脱这种黑客攻击的地步,需要能够正确地模拟我的服务层。
为什么在
when(service.save(isA(Policy.class))).thenReturn(new Policy());PolicyService
中不加入并模拟出save方法?我是否在某处缺少某些Mockito配置?我需要在Spring配置中添加一些内容吗?到目前为止,我的研究仅限于谷歌搜索“ spring mvc test Mockito不起作用”,但这并没有给我带来太多帮助。谢谢。
更新1
你是正确的@ tom-verelst
,我指的是PolicyService service
;测试中的那行,因此,MockMvc遗嘱中的服务当然已由Spring注入。然后,我尝试标注
private MockMvc mockMvc
有@InjectMocks
和仍然得到了同样的问题(即内部的服务MockMvc是不是因为我是期待它是嘲笑)。我已经在调试过程PolicyServiceImpl
中调用上的save方法的位置添加了堆栈跟踪(这与模拟服务中对save方法的期望调用相反)。Thread [main] (Suspended (breakpoint at line 29 in DomainEntityServiceImpl) PolicyServiceImpl(DomainEntityServiceImpl<T>).save(T) line: 29 NativeMethodAccessorImpl.invoke0(Method,Object,Object[]) line: not available [native method] NativeMethodAccessorImpl.invoke(Object,Object[]) line: 39 DelegatingMethodAccessorImpl.invoke(Object,Object[]) line: 25 Method.invoke(Object,Object...) line: 597 AopUtils.invokeJoinpointUsingReflection(Object,Method,Object[]) line: 317 ReflectiveMethodInvocation.invokeJoinpoint() line: 183 ReflectiveMethodInvocation.proceed() line: 150 TransactionInterceptor$1.proceedWithInvocation() line: 96 TransactionInterceptor(TransactionAspectSupport).invokeWithinTransaction(Method,Class,TransactionAspectSupport$InvocationCallback) line: 260 TransactionInterceptor.invoke(MethodInvocation) line: 94 ReflectiveMethodInvocation.proceed() line: 172 JdkDynamicAopProxy.invoke(Object,Object[]) line: 204 $Proxy44.save(DomainEntity) line: not available PolicyController.createOrUpdate(Policy,BindingResult) line: 64 NativeMethodAccessorImpl.invoke0(Method,Object...) line: 597 ServletInvocableHandlerMethod(InvocableHandlerMethod).invoke(Object...) line: 219 ServletInvocableHandlerMethod(InvocableHandlerMethod).invokeForRequest(NativeWebRequest,ModelAndViewContainer,Object...) line: 132 ServletInvocableHandlerMethod.invokeAndHandle(ServletWebRequest,Object...) line: 104 RequestMappingHandlerAdapter.invokeHandleMethod(HttpServletRequest,HttpServletResponse,HandlerMethod) line: 746 RequestMappingHandlerAdapter.handleInternal(HttpServletRequest,HandlerMethod) line: 687 RequestMappingHandlerAdapter(AbstractHandlerMethodAdapter).handle(HttpServletRequest,Object) line: 80 TestDispatcherServlet(DispatcherServlet).doDispatch(HttpServletRequest,HttpServletResponse) line: 925 TestDispatcherServlet(DispatcherServlet).doService(HttpServletRequest,HttpServletResponse) line: 856 TestDispatcherServlet(FrameworkServlet).processRequest(HttpServletRequest,HttpServletResponse) line: 915 TestDispatcherServlet(FrameworkServlet).doPost(HttpServletRequest,HttpServletResponse) line: 822 TestDispatcherServlet(HttpServlet).service(HttpServletRequest,HttpServletResponse) line: 727 TestDispatcherServlet(FrameworkServlet).service(HttpServletRequest,HttpServletResponse) line: 796 TestDispatcherServlet.service(HttpServletRequest,HttpServletResponse) line: 66 TestDispatcherServlet(HttpServlet).service(ServletRequest,ServletResponse) line: 820 MockFilterChain$ServletFilterProxy.doFilter(ServletRequest,ServletResponse,FilterChain) line: 168 MockFilterChain.doFilter(ServletRequest,ServletResponse) line: 136 MockMvc.perform(RequestBuilder) line: 134 PolicyControllerTest.createOrUpdateSuccessful() line: 67 NativeMethodAccessorImpl.invoke0(Method,Object...) line: 597 FrameworkMethod$1.runReflectiveCall() line: 44 FrameworkMethod$1(ReflectiveCallable).run() line: 15 FrameworkMethod.invokeExplosively(Object,Object...) line: 41 InvokeMethod.evaluate() line: 20 RunBefores.evaluate() line: 28 RunBeforeTestMethodCallbacks.evaluate() line: 74 RunAfterTestMethodCallbacks.evaluate() line: 83 SpringRepeat.evaluate() line: 72 SpringJUnit4ClassRunner.runChild(FrameworkMethod,RunNotifier) line: 231 SpringJUnit4ClassRunner.runChild(Object,RunNotifier) line: 88 ParentRunner$3.run() line: 193 ParentRunner$1.schedule(Runnable) line: 52 SpringJUnit4ClassRunner(ParentRunner<T>).runChildren(RunNotifier) line: 191 ParentRunner<T>.access$000(ParentRunner,RunNotifier) line: 42 ParentRunner$2.evaluate() line: 184 RunBeforeTestClassCallbacks.evaluate() line: 61 RunAfterTestClassCallbacks.evaluate() line: 71 SpringJUnit4ClassRunner(ParentRunner<T>).run(RunNotifier) line: 236 SpringJUnit4ClassRunner.run(RunNotifier) line: 174 JUnit4TestMethodReference(JUnit4TestReference).run(TestExecution) line: 50 TestExecution.run(ITestReference[]) line: 38 RemoteTestRunner.runTests(String[],String,TestExecution) line: 467 RemoteTestRunner.runTests(TestExecution) line: 683 RemoteTestRunner.run() line: 390 RemoteTestRunner.main(String[]) line: 197
进一步的研究(使用@Mock时将Mockito注入Null值到Spring bean中?)建议在测试中将其
@InjectMocks
应用于PolicyController
成员变量,但是正如第一个链接中的一个答案所指出的那样,此操作无济于事,因为Spring没有一无所知。
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.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({ "classpath:/applicationContext.xml","classpath:/tests_persistence-applicationContext.xml" })
public class PolicyControllerTest {
@Mock
PolicyService service;
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
// this must be called for the @Mock annotations above to be processed.
MockitoAnnotations.initMocks(this);
}
@Test
public void createOrUpdateFailsWhenInvalidDataPostedAndSendsUserBackToForm() throws Exception {
// Post no parameters in this request to force errors
mockMvc.perform(post("/policies/persist")).andExpect(status().isOk())
.andExpect(model().attributeHasErrors("policy"))
.andExpect(view().name("createOrUpdatePolicy"));
}
@Test
public void createOrUpdateSuccessful() throws Exception {
// Mock the service method to force a known response
when(service.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"));
}
}
Thread [main] (Suspended (breakpoint at line 29 in DomainEntityServiceImpl) PolicyServiceImpl(DomainEntityServiceImpl<T>).save(T) line: 29
NativeMethodAccessorImpl.invoke0(Method,Object,Object[]) line: not available [native method]
NativeMethodAccessorImpl.invoke(Object,Object[]) line: 39
DelegatingMethodAccessorImpl.invoke(Object,Object[]) line: 25
Method.invoke(Object,Object...) line: 597
AopUtils.invokeJoinpointUsingReflection(Object,Method,Object[]) line: 317
ReflectiveMethodInvocation.invokeJoinpoint() line: 183
ReflectiveMethodInvocation.proceed() line: 150
TransactionInterceptor$1.proceedWithInvocation() line: 96
TransactionInterceptor(TransactionAspectSupport).invokeWithinTransaction(Method,Class,TransactionAspectSupport$InvocationCallback) line: 260
TransactionInterceptor.invoke(MethodInvocation) line: 94
ReflectiveMethodInvocation.proceed() line: 172
JdkDynamicAopProxy.invoke(Object,Object[]) line: 204
$Proxy44.save(DomainEntity) line: not available
PolicyController.createOrUpdate(Policy,BindingResult) line: 64
NativeMethodAccessorImpl.invoke0(Method,Object...) line: 597
ServletInvocableHandlerMethod(InvocableHandlerMethod).invoke(Object...) line: 219
ServletInvocableHandlerMethod(InvocableHandlerMethod).invokeForRequest(NativeWebRequest,ModelAndViewContainer,Object...) line: 132
ServletInvocableHandlerMethod.invokeAndHandle(ServletWebRequest,Object...) line: 104
RequestMappingHandlerAdapter.invokeHandleMethod(HttpServletRequest,HttpServletResponse,HandlerMethod) line: 746
RequestMappingHandlerAdapter.handleInternal(HttpServletRequest,HandlerMethod) line: 687
RequestMappingHandlerAdapter(AbstractHandlerMethodAdapter).handle(HttpServletRequest,Object) line: 80
TestDispatcherServlet(DispatcherServlet).doDispatch(HttpServletRequest,HttpServletResponse) line: 925
TestDispatcherServlet(DispatcherServlet).doService(HttpServletRequest,HttpServletResponse) line: 856
TestDispatcherServlet(FrameworkServlet).processRequest(HttpServletRequest,HttpServletResponse) line: 915
TestDispatcherServlet(FrameworkServlet).doPost(HttpServletRequest,HttpServletResponse) line: 822
TestDispatcherServlet(HttpServlet).service(HttpServletRequest,HttpServletResponse) line: 727
TestDispatcherServlet(FrameworkServlet).service(HttpServletRequest,HttpServletResponse) line: 796
TestDispatcherServlet.service(HttpServletRequest,HttpServletResponse) line: 66
TestDispatcherServlet(HttpServlet).service(ServletRequest,ServletResponse) line: 820
MockFilterChain$ServletFilterProxy.doFilter(ServletRequest,ServletResponse,FilterChain) line: 168
MockFilterChain.doFilter(ServletRequest,ServletResponse) line: 136
MockMvc.perform(RequestBuilder) line: 134
PolicyControllerTest.createOrUpdateSuccessful() line: 67
NativeMethodAccessorImpl.invoke0(Method,Object...) line: 597
FrameworkMethod$1.runReflectiveCall() line: 44
FrameworkMethod$1(ReflectiveCallable).run() line: 15
FrameworkMethod.invokeExplosively(Object,Object...) line: 41
InvokeMethod.evaluate() line: 20
RunBefores.evaluate() line: 28
RunBeforeTestMethodCallbacks.evaluate() line: 74
RunAfterTestMethodCallbacks.evaluate() line: 83
SpringRepeat.evaluate() line: 72
SpringJUnit4ClassRunner.runChild(FrameworkMethod,RunNotifier) line: 231
SpringJUnit4ClassRunner.runChild(Object,RunNotifier) line: 88
ParentRunner$3.run() line: 193
ParentRunner$1.schedule(Runnable) line: 52
SpringJUnit4ClassRunner(ParentRunner<T>).runChildren(RunNotifier) line: 191
ParentRunner<T>.access$000(ParentRunner,RunNotifier) line: 42
ParentRunner$2.evaluate() line: 184
RunBeforeTestClassCallbacks.evaluate() line: 61
RunAfterTestClassCallbacks.evaluate() line: 71
SpringJUnit4ClassRunner(ParentRunner<T>).run(RunNotifier) line: 236
SpringJUnit4ClassRunner.run(RunNotifier) line: 174
JUnit4TestMethodReference(JUnit4TestReference).run(TestExecution) line: 50
TestExecution.run(ITestReference[]) line: 38
RemoteTestRunner.runTests(String[],String,TestExecution) line: 467
RemoteTestRunner.runTests(TestExecution) line: 683
RemoteTestRunner.run() line: 390
RemoteTestRunner.main(String[]) line: 197
关于Spring方面,我仍然非常学习,因此欢迎任何可以改善我的解释的评论很有帮助。
我有一个Spring 3.2 MVC应用程序,并且正在使用Spring MVC测试框架来测试控制器操作上的GET和POST请求。我正在使用Mockito模拟服务,但是发现模拟被忽略并且正在使用我的实际服务层(因此,数据库被命中)。
我的Controller测试中的代码:
你会注意到我有两个上下文配置文件;这是一个黑客,因为如果我无法阻止控制器测试到达实际的服务层,则该服务层也可能会将其存储库指向测试数据库。我已经到了无法再摆脱这种黑客攻击的地步,需要能够正确地模拟我的服务层。
为什么在when(service.save(isA(Policy.class))).thenReturn(new Policy());PolicyService
中不加入并模拟出save方法?我是否在某处缺少某些Mockito配置?我需要在Spring配置中添加一些内容吗?到目前为止,我的研究仅限于谷歌搜索“ spring mvc test Mockito不起作用”,但这并没有给我带来太多帮助。
谢谢。
更新1
你是正确的@ tom-verelst
,我指的是PolicyService service
;测试中的那行,因此,MockMvc遗嘱中的服务当然已由Spring注入。
然后,我尝试标注private MockMvc mockMvc
有@InjectMocks
和仍然得到了同样的问题(即内部的服务MockMvc是不是因为我是期待它是嘲笑)。我已经在调试过程PolicyServiceImpl
中调用上的save方法的位置添加了堆栈跟踪(这与模拟服务中对save方法的期望调用相反)。
进一步的研究(使用@Mock时将Mockito注入Null值到Spring bean中?)建议在测试中将其@InjectMocks
应用于PolicyController
成员变量,但是正如第一个链接中的一个答案所指出的那样,此操作无济于事,因为Spring没有一无所知。
关于Spring方面,我仍然非常学习,因此欢迎任何可以改善我的解释的评论很有帮助。