使用自动装配存储库测试 Spring 引导 MVC
Testing Spring Boot MVC with autowired repositories
我有两个项目。一个叫 myCore
,一个叫 myWeb
。 myCore
包含所有 bean 和存储库接口。 myWeb
只是一个 JSON api 将 myCore
作为依赖引入。当我 运行 myWeb
一切正常。当我尝试 运行 针对 myWeb
中的控制器进行单元测试时,@Autowired
存储库是 null
。我需要找到一些方法让 @Autowired
存储库接口具有与应用程序 运行ning 时相同的值,或者模拟这些对象。最好我想知道如何实施这两种解决方案。
myCore pom.xml
:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.12.4</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.6.1.RELEASE</version>
</dependency>
myCore
context.xml
<mongo:repositories base-package="com.myOrg.myapp.repo.mongo" />
<mongo:db-factory id="dbfactory" host="removed"
port="removed" dbname="removed" username="removed" password="removed" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="dbfactory" />
</bean>
回购接口:
public interface SiteRepository extends PagingAndSortingRepository<Site, String>{
void findBySomethingCustom(String somethingCustom);
}
在网络项目中:
'我的网站` pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>com.myOrg.myApp.Application</start-class>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.myOrg</groupId>
<artifactId>myCore</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
myWeb
配置:
@Configuration
@ImportResource("classpath*:/spring/context.xml")
public class Config {}
myWeb
控制器:
@RestController
@RequestMapping("site")
public class SiteController {
@Autowired
private SiteRepository siteRepo;
@RequestMapping(value = "", method = RequestMethod.GET)
public Iterable<Site> getSites() {
return siteRepo.findAll();
}
}
最后,测试 class:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
@ContextConfiguration(classes = Config.class)
public class SiteControllerTest {
private MockMvc mvc;
@Before
public void setUp() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new SiteController()).build();
}
@Test
public void testGetSites() throws Exception {
mvc.perform(
MockMvcRequestBuilders.get("/site"));
}
}
我在 testGetSites() 中收到空指针异常,表明 siteRepo 为空。但是,导航到该控制器方法的 url 会正常执行。
同样,我需要它在应用程序 运行 正常时具有它所具有的值,and/or 一种模拟该对象的方法,以便测试可以正常通过(或失败)。
更新
改变了
mvc = MockMvcBuilders.standaloneSetup(new SiteController()).build();
至
mvc = MockMvcBuilders.webAppContextSetup(wac).build();
其中 wac
引用
@Autowired
private WebApplicationContext wac;
也改变了:
@SpringApplicationConfiguration(classes = {MockServletContext.class}
至
@SpringApplicationConfiguration(classes = {Application.class})
我认为 NPE 是由 mvc = MockMvcBuilders.standaloneSetup(new SiteController())
引起的。 Javadoc 说:
This allows full control over the instantiation and initialization of
controllers, and their dependencies, similar to plain unit tests while
also making it possible to test one controller at a time.
在我的解释中,这意味着您有责任提供所有依赖项(例如,您可以提供模拟等)。由于您刚刚创建了没有任何依赖项的新实例,因此您遇到了 NPE。
所以我看到了两个解决方案:
提供您自己的模拟依赖项
如果您希望spring为您解决依赖关系,请改用webAppContextSetup.webAppContextSetup
。
我有两个项目。一个叫 myCore
,一个叫 myWeb
。 myCore
包含所有 bean 和存储库接口。 myWeb
只是一个 JSON api 将 myCore
作为依赖引入。当我 运行 myWeb
一切正常。当我尝试 运行 针对 myWeb
中的控制器进行单元测试时,@Autowired
存储库是 null
。我需要找到一些方法让 @Autowired
存储库接口具有与应用程序 运行ning 时相同的值,或者模拟这些对象。最好我想知道如何实施这两种解决方案。
myCore pom.xml
:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.12.4</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.6.1.RELEASE</version>
</dependency>
myCore
context.xml
<mongo:repositories base-package="com.myOrg.myapp.repo.mongo" />
<mongo:db-factory id="dbfactory" host="removed"
port="removed" dbname="removed" username="removed" password="removed" />
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="dbfactory" />
</bean>
回购接口:
public interface SiteRepository extends PagingAndSortingRepository<Site, String>{
void findBySomethingCustom(String somethingCustom);
}
在网络项目中: '我的网站` pom.xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>com.myOrg.myApp.Application</start-class>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.myOrg</groupId>
<artifactId>myCore</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
myWeb
配置:
@Configuration
@ImportResource("classpath*:/spring/context.xml")
public class Config {}
myWeb
控制器:
@RestController
@RequestMapping("site")
public class SiteController {
@Autowired
private SiteRepository siteRepo;
@RequestMapping(value = "", method = RequestMethod.GET)
public Iterable<Site> getSites() {
return siteRepo.findAll();
}
}
最后,测试 class:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
@ContextConfiguration(classes = Config.class)
public class SiteControllerTest {
private MockMvc mvc;
@Before
public void setUp() throws Exception {
mvc = MockMvcBuilders.standaloneSetup(new SiteController()).build();
}
@Test
public void testGetSites() throws Exception {
mvc.perform(
MockMvcRequestBuilders.get("/site"));
}
}
我在 testGetSites() 中收到空指针异常,表明 siteRepo 为空。但是,导航到该控制器方法的 url 会正常执行。
同样,我需要它在应用程序 运行 正常时具有它所具有的值,and/or 一种模拟该对象的方法,以便测试可以正常通过(或失败)。
更新
改变了
mvc = MockMvcBuilders.standaloneSetup(new SiteController()).build();
至
mvc = MockMvcBuilders.webAppContextSetup(wac).build();
其中 wac
引用
@Autowired
private WebApplicationContext wac;
也改变了:
@SpringApplicationConfiguration(classes = {MockServletContext.class}
至
@SpringApplicationConfiguration(classes = {Application.class})
我认为 NPE 是由 mvc = MockMvcBuilders.standaloneSetup(new SiteController())
引起的。 Javadoc 说:
This allows full control over the instantiation and initialization of controllers, and their dependencies, similar to plain unit tests while also making it possible to test one controller at a time.
在我的解释中,这意味着您有责任提供所有依赖项(例如,您可以提供模拟等)。由于您刚刚创建了没有任何依赖项的新实例,因此您遇到了 NPE。
所以我看到了两个解决方案:
提供您自己的模拟依赖项
如果您希望spring为您解决依赖关系,请改用
webAppContextSetup.webAppContextSetup
。