2016-01-24 105 views
1

我的JUnit测试用例失败。误差在线中发生Spring MVC应用程序Junit测试用例失败

Mockito.when(blogEntryService.find(1L))thenReturn(条目)。

失败扫描线为 com.sample.controller.BlogEntryControllerTest.getExistingBlogEntry(BlogEntryControllerTest.java:72)

显示java.lang.NullPointerException 在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)在 sun.reflect.NativeMethodAccessorImpl.invoke(未知来源)处 java.lang.reflect.Method.invoke(未知来源) sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源)在 org.junit.runners。 model.FrameworkMethod $ 1.runRef lectiveCall(FrameworkMethod.java:50) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java: 47) 在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 在 org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 在 org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 在 org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestM ethodCallbacks.java:83) 在 org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(基于SpringJUnit4ClassRunner。 Java的:233) 在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87) 在org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:290)在 组织。 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)at org.junit.runners.ParentRunner.access $ 000(ParentRunner.java: 58)在 org.junit.runners.ParentRunner $ 2。评估(ParentRunner.java:268)在 org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 在 org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate (RunAfterTestClassCallbacks.java:71) 在org.junit.runners.ParentRunner.run(ParentRunner.java:363)在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:176) 在 org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run在 org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)(JUnit4TestReference.java:50) 在 org.eclipse .jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 在 org.eclipse .jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner。Java的:197)

在我看来那blogEntryService为空

我的代码是

/** 
* TODO - Describe purpose and operation of class. 
* 
* <table border="1" cellpadding="0" cellspacing="0" width="100%"> 
* <caption align="center">Edit and Version History</caption> 
* <tr><th>Version</th><th>Date</th><th>Author</th><th>Description</th></tr> 
* <tr><td>1.0</td><td>Jan 17, 2016</td><td>EOV537</td><td>Initial creation.</td></tr> 
* </table> 
*/ 
package com.sample.controller; 

import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; 
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; 

import org.hamcrest.Matchers; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.mockito.InjectMocks; 
import org.mockito.Mock; 
import org.mockito.Mockito; 
import org.mockito.MockitoAnnotations; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.http.MediaType; 
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.request.MockMvcRequestBuilders; 
import org.springframework.test.web.servlet.result.MockMvcResultMatchers; 
import org.springframework.test.web.servlet.setup.MockMvcBuilders; 
import org.springframework.web.context.WebApplicationContext; 

import com.sample.config.ApplicationConfig; 
import com.sample.model.BlogEntry; 
import com.sample.service.BlogEntryService; 

/** 
* @author EOV537 - 
* @since 1.0 
*/ 
@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = {ApplicationConfig.class}) 
@WebAppConfiguration 
public class BlogEntryControllerTest { 

    private MockMvc mockMvc; 

    @InjectMocks 
    private BlogEntryController blogentryconttroller; 

    @Mock 
    private BlogEntryService blogEntryService; 

    @Autowired 
    private WebApplicationContext appCtx; 

    @Before 
    public void setup() { 

     MockitoAnnotations.initMocks(BlogEntryControllerTest.class); 
     mockMvc = MockMvcBuilders.webAppContextSetup(appCtx).build(); 
    } 

    @Test 
    public void getExistingBlogEntry() throws Exception { 

     BlogEntry entry = new BlogEntry(); 
     entry.setId(1L); 
     entry.setTitle("Test Title"); 

     Mockito.when(blogEntryService.find(1L)).thenReturn(entry); 

     mockMvc.perform(MockMvcRequestBuilders.get("/rest/blog-entries/1")) 
       .andExpect(MockMvcResultMatchers.jsonPath("$.title", Matchers.is("Test Title"))) 
       .andExpect(
         MockMvcResultMatchers.jsonPath("$.links[*].href", 
           Matchers.hasItem(Matchers.endsWith("/blog-entries/1")))) 
       .andExpect(MockMvcResultMatchers.status().isOk()); 
    } 

    public void getNonExistingBlogEntry() throws Exception { 

     Mockito.when(blogEntryService.find(1L)).thenReturn(null); 
     mockMvc.perform(MockMvcRequestBuilders.get("/rest/blog-entries/1")).andExpect(
       MockMvcResultMatchers.status().isNotFound()); 
    } 



} 

BlogEntryController.Java

package com.sample.controller; 

import org.springframework.http.HttpStatus; 
import org.springframework.http.ResponseEntity; 
import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.PathVariable; 
import org.springframework.web.bind.annotation.RequestBody; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.RestController; 

import com.sample.assembler.BlogEntryResourceAsm; 
import com.sample.model.BlogEntry; 
import com.sample.resource.BlogEntryResource; 
import com.sample.service.BlogEntryService; 

/** 
* @author EOV537 - 
* @since 1.0 
*/ 
@Controller 
@RequestMapping(value = "/rest/blog-enteries") 
public class BlogEntryController { 

    public BlogEntryController() { 

    } 

    public BlogEntryController(BlogEntryService blogEntryService) { 

     this.blogEntryService = blogEntryService; 
    } 

    private BlogEntryService blogEntryService; 

    @RequestMapping(value = "/{blogEntryId}", method = RequestMethod.GET) 
    public ResponseEntity<BlogEntryResource> getExsitingBlogEntry(@PathVariable Long blogEntryId) { 

     BlogEntry entry = blogEntryService.find(blogEntryId); 

     if (entry != null) { 
      BlogEntryResource res = new BlogEntryResourceAsm().toResource(entry); 
      return new ResponseEntity<BlogEntryResource>(res, HttpStatus.OK); 
     } else { 
      return new ResponseEntity<BlogEntryResource>(HttpStatus.NOT_FOUND); 
     } 
    } 

} 

BlogEntryService.Java

package com.sample.service; 

import org.springframework.stereotype.Component; 

import com.sample.model.BlogEntry; 

/** 
* @author EOv537 - 
* 
* @since 1.0 
*/ 

public interface BlogEntryService { 
    public BlogEntry find(Long id); 
} 

BlogEntryResource.java

package com.sample.resource; 

import org.springframework.hateoas.ResourceSupport; 

/** 
* @author EOv537 - 
* @since 1.0 
*/ 
public class BlogEntryResource extends ResourceSupport { 

    private String title; 

    public String getTitle() { 
     return title; 
    } 

    public void setTitle(String title) { 
     this.title = title; 
    } 

} 

BlogEntryResourceAsm.java

public class BlogEntryResourceAsm extends ResourceAssemblerSupport<BlogEntry, BlogEntryResource> { 

    /** 
    * @param controllerClass 
    * @param resourceType 
    */ 
    public BlogEntryResourceAsm() { 
     super(BlogEntryController.class, BlogEntryResource.class); 
     // TODO Auto-generated constructor stub 
    } 

    /* 
    * (non-Javadoc) 
    * 
    * @see org.springframework.hateoas.ResourceAssembler#toResource(java.lang.Object) 
    */ 
    @Override 
    public BlogEntryResource toResource(BlogEntry blogEntry) { 

     BlogEntryResource res = new BlogEntryResource(); 
     res.setTitle(blogEntry.getTitle()); 
     Link link = ControllerLinkBuilder.linkTo(BlogEntryController.class).slash(blogEntry.getId()).withSelfRel(); 
     return res; 

    } 
} 

ApplicationConfig.java

/** 
* TODO - Describe purpose and operation of class. 
* 
* <table border="1" cellpadding="0" cellspacing="0" width="100%"> 
* <caption align="center">Edit and Version History</caption> 
* <tr><th>Version</th><th>Date</th><th>Author</th><th>Description</th></tr> 
* <tr><td>1.0</td><td>Jan 17, 2016</td><td>EOV537</td><td>Initial creation.</td></tr> 
* </table> 
*/ 
package com.sample.config; 

import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.web.servlet.ViewResolver; 
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; 
import org.springframework.web.servlet.config.annotation.EnableWebMvc; 
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 
import org.springframework.web.servlet.view.InternalResourceViewResolver; 

/** 
* @author EOV537 - 
* @since 1.0 
*/ 
@Configuration 
@EnableWebMvc 
@ComponentScan(basePackages = {"com.sample"}) 
public class ApplicationConfig extends WebMvcConfigurerAdapter { 

    private static final String VIEW_RESOLVER_PREFIX = "/WEB-INF/jsp/"; 

    private static final String VIEW_RESOLVER_SUFFIX = ".jsp"; 

    @Override 
    public void addResourceHandlers(ResourceHandlerRegistry registry) { 
     registry.addResourceHandler("/static/**").addResourceLocations("/static/"); 
    } 

    @Override 
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { 
     configurer.enable(); 
    } 

    @Bean 
    public ViewResolver viewResolver() { 
     InternalResourceViewResolver viewResolver = new InternalResourceViewResolver(); 

     // viewResolver.setViewClass(InternalResourceViewResolver.class); // NOSONAR 
     viewResolver.setPrefix(VIEW_RESOLVER_PREFIX); 
     viewResolver.setSuffix(VIEW_RESOLVER_SUFFIX); 

     return viewResolver; 
    } 

} 

WebApplint.java

/** 
* TODO - Describe purpose and operation of class. 
* 
* <table border="1" cellpadding="0" cellspacing="0" width="100%"> 
* <caption align="center">Edit and Version History</caption> 
* <tr><th>Version</th><th>Date</th><th>Author</th><th>Description</th></tr> 
* <tr><td>1.0</td><td>Jan 17, 2016</td><td>EOV537</td><td>Initial creation.</td></tr> 
* </table> 
*/ 
package com.sample.config; 

import javax.servlet.ServletContext; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRegistration; 

import org.springframework.web.WebApplicationInitializer; 
import org.springframework.web.context.ContextLoaderListener; 
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; 
import org.springframework.web.servlet.DispatcherServlet; 

/** 
* @author EOV537 - 
* @since 1.0 
*/ 
public class WebApplint implements WebApplicationInitializer { 
    /* 
    * (non-Javadoc) 
    * 
    * @see org.springframework.web.WebApplicationInitializer#onStartup(javax.servlet.ServletContext) 
    */ 
    @Override 
    public void onStartup(ServletContext servletContext) throws ServletException { 

     AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); 
     rootContext.register(ApplicationConfig.class); 

     ServletRegistration.Dynamic registration = servletContext.addServlet("DispatcherServlet", 
       new DispatcherServlet(rootContext)); 

     registration.addMapping("/"); 

     registration.setLoadOnStartup(1); 
     servletContext.addListener(new ContextLoaderListener(rootContext)); 

    } 
} 

回答

1
private MockMvc mockMvc; 

@Autowired 
@InjectMocks 
private BlogEntryController blogentryconttroller; 

@Autowired 
private WebApplicationContext appCtx; 

@Mock 
BlogEntryService blogEntryService; 

@Before 
public void setup() { 
    MockitoAnnotations.initMocks(BlogEntryControllerTest.this); 
    mockMvc = MockMvcBuilders.webAppContextSetup(appCtx).build(); 
} 

@Test 
public void getExistingBlogEntry() throws Exception { 
    BlogEntry entry = new BlogEntry(); 
    entry.setId(1L); 
    entry.setTitle("Test Title"); 
    Mockito.when(blogEntryService.find(1L)).thenReturn(entry); 
    mockMvc.perform(MockMvcRequestBuilders.get("/rest/blog-enteries/1")) 
      .andExpect(MockMvcResultMatchers.status().isOk()); 
} 
+0

我想使用注释 @Mock private BlogEntryService blogEntryService;如果你看到我的班级已经有这种方法是不正确的? – Satya

+0

使用您的解决方案BlogEntryService blogEntryService = Mockito.mock(BlogEntryService.class); Mockito给我代理实现,我不需要添加实现和初始化,但我从来不明白为什么@mock不起作用。 – Satya

+0

我没有初始化看到我的代码MockitoAnnotations.initMocks(BlogEntryControllerTest.class); – Satya

0

在BlogEntryController()中,blogEntryService从不初始化为一个值。在您的@Before(设置())方法,初始化blogEntryService:

blogEntryService = new BlogEntryService(); 
+0

blogEntryService是Interface它无法解析为变量。请参阅代码 – Satya

0

罗希特的回答上面帮助和解决以下是替代我试着和它的工作原来嘲讽的问题,但它仅仅是替代不是解决办法。

我评论以下行

//@RunWith(SpringJUnit4ClassRunner.class) 
//@ContextConfiguration(classes = {ApplicationConfig.class}) 
从BlogEntryControllerTest

。的java

我改变设置()方法从BlogEntryControllerTest到

@Before 
public void setup() { 

    // blogEntryService = Mockito.mock(BlogEntryService.class); 
    MockitoAnnotations.initMocks(this); 
    mockMvc = MockMvcBuilders.standaloneSetup(blogentryconttroller).build(); 
    //mockMvc = MockMvcBuilders.webAppContextSetup(appCtx).build(); 

} 

相反webAppContextSetup它是变化StandaloneSetup 然后

更新BlogEntryController除去默认的构造

// public BlogEntr yController(){

//}

现在只有1构造

公共BlogEntryController(BlogEntryService blogEntryService){

this.blogEntryService = blogEntryService; 
} 

现在,当我执行测试mocked blogEntryService正在被正确注入。

当我使用webAppContextSetup时,我必须保留 BlogEntryController的默认构造函数。既然它有默认的构造函数,所以当我运行测试 默认的构造函数得到执行,并且blogEntryService保持为空并且测试失败。

即使我能够得到这个工作,这不是解决方案,它只是一个替代方案。

如果有人知道如何通过webAppContextSetup解决此问题,请发布解决方案。