MockMvc中測試產生的問題org.springframework.web.util.NestedServletException


通過Mock測試Spring MVC發生的問題:

    @Test
    public void shouldProcessRegistration() throws Exception{
        SpitterRepository mockReopsitory =   Mockito.mock(SpitterRepository.class); //通過Mock生成一個虛擬的對象實例SpitterRepository是一個接口且沒有實例化,只能虛擬
        
        Spitter unsaved = new Spitter("jbauer","24hours","Jack","Bauer"); //新鍵了兩個實例
        Spitter saved=new Spitter(24L,"jbauer","24hours","Jack","Bauer");
        Mockito.when(mockReopsitory.save(unsaved)).thenReturn(saved);  //當mockReopsitory存儲UNsaved之后返回saved對象
        
        SpitterController controller = new SpitterController(mockReopsitory);//傳入mockReopsitory,因為SpitterController包含這個成員變量的
        
        MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build();//單獨建立controller這個虛擬MVC
//在構建完SpitterRepository的mock實現以及所要執行的控制器和MockMvc之后,shouldProcess-Registration()對“/spitter/register”發起了一個POST請求。
   //作為請求的一部分,用戶信息以參數的形式放到request中,從而模擬提交的表單。 mockMvc.perform(MockMvcRequestBuilders.post(
"/spitter/register") .param("firstName", "Jack") .param("lastName", "Bauer") .param("username", "jbauer") .param("password", "24hours")) .andExpect(MockMvcResultMatchers.redirectedUrl("/spitter/jbauer")); Mockito.verify(mockReopsitory, Mockito.atLeastOnce()).save(unsaved); //測試會校驗SpitterRepository的mock實現最終會真正用來保存表單上傳入的數據。 } }

 

    @RequestMapping(value="/register",method=RequestMethod.POST)
    public String processRegistration(Spitter spitter){
        spitterRepository.save(spitter);
        return "redirect:/spitter/" +spitter.getUsername();
    }

 

錯誤一:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [spittr.Spitter]: No default constructor found; nested exception is java.lang.NoSuchMethodException: spittr.Spitter.<init>()
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:973)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:64)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:170)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:137)
at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:141)
at spittr.test.HomeControllerTest.shouldProcessRegistration(HomeControllerTest.java:109)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [spittr.Spitter]: No default constructor found; nested exception is java.lang.NoSuchMethodException: spittr.Spitter.<init>()
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:108)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:81)
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:104)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:79)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:157)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:124)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:690)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:876)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
... 32 more
Caused by: java.lang.NoSuchMethodException: spittr.Spitter.<init>()
at java.lang.Class.getConstructor0(Class.java:2810)
at java.lang.Class.getDeclaredConstructor(Class.java:2053)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:105)
... 45 more

 原因:No default constructor found;

由於mockMvc.perform(MockMvcRequestBuilders.post("/spitter/register"),要調用無參的構造函數構造對象。

當Spitter類中的沒有定義無參的構造函數,報錯。

 

錯誤二:

java.lang.AssertionError: Redirected URL expected:</spitter/jbauer> but was:</spitter/null>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89)
at org.springframework.test.web.servlet.result.MockMvcResultMatchers$3.match(MockMvcResultMatchers.java:127)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:149)
at spittr.test.HomeControllerTest.shouldProcessRegistration(HomeControllerTest.java:114)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

 原因:andExpect(MockMvcResultMatchers.redirectedUrl("/spitter/jbauer"))

當修改錯誤的錯誤之后,產生url錯誤,原因:在processRegistration的參數時一個對象,當傳入參數的是后,是要默認調用參數的setter方法的,

所以,要在Spitter類中添加對應的setter方法。

或者改為:就不用添加setter方法了

@RequestMapping(value="/register",method=RequestMethod.POST)
    public String processRegistration(
            @RequestParam("firstName") String firstName,
            @RequestParam("lastName") String lastName,
            @RequestParam("username") String username,
            @RequestParam("password") String password){
        spitterRepository.save(new Spitter(firstName, lastName, username, password));
        return "redirect:/spitter/" + username;
    }

 

 

錯誤三:

Argument(s) are different! Wanted:
spitterRepository.save(
spittr.Spitter@fa21b3e
);
-> at spittr.test.HomeControllerTest.shouldProcessRegistration(HomeControllerTest.java:115)
Actual invocation has different arguments:
spitterRepository.save(
spittr.Spitter@5baa8b76
);
-> at spittr.web.SpitterController.processRegistration(SpitterController.java:34)

原因,比較兩個對象默認是比較的對象的地址。

需要重寫其比較的方法

 

 
         

    import org.apache.commons.lang3.builder.EqualsBuilder;
    import org.apache.commons.lang3.builder.HashCodeBuilder;


@Override
public boolean equals(Object that) { return EqualsBuilder.reflectionEquals(this, that, "firstName", "lastName", "username", "password", "email"); } @Override public int hashCode() { return HashCodeBuilder.reflectionHashCode(this, "firstName", "lastName", "username", "password", "email"); }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM