【问题标题】:Testing Spring Boot MVC with autowired repositories使用自动装配的存储库测试 Spring Boot MVC
【发布时间】:2015-03-20 14:50:44
【问题描述】:

我有两个项目。一个叫myCore,一个叫myWebmyCore包含所有 bean 和存储库接口。 myWeb 只是一个 JSON api,它引入了 myCore 作为依赖项。当我运行myWeb 时,一切正常。当我尝试对myWeb 中的控制器运行单元测试时,@Autowired 存储库是null。我需要找到某种方法让@Autowired 存储库接口具有与应用程序运行时相同的值,或者模拟这些对象。最好我想知道如何实现这两种解决方案。

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>

myCorecontext.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>

repo 接口:

public interface SiteRepository extends PagingAndSortingRepository<Site, String>{

    void findBySomethingCustom(String somethingCustom);
}

在网络项目中: 'myWeb` 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();
    }
}

最后是测试类:

@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 会正常执行。

同样,我需要它具有应用程序正常运行时的值,和/或模拟该对象的方法,以便测试可以正常通过(或失败)。

更新 改变了 mvc = MockMvcBuilders.standaloneSetup(new SiteController()).build();mvc = MockMvcBuilders.webAppContextSetup(wac).build(); 其中wac 引用

@Autowired
private WebApplicationContext wac;

也改变了:

@SpringApplicationConfiguration(classes = {MockServletContext.class}

@SpringApplicationConfiguration(classes = {Application.class})

【问题讨论】:

    标签: spring unit-testing maven spring-mvc spring-boot


    【解决方案1】:

    我相信 NPE 是由mvc = MockMvcBuilders.standaloneSetup(new SiteController()) 引起的。 Javadoc 说:

    这允许完全控制实例化和初始化 控制器及其依赖项,类似于普通的单元测试,而 还可以一次测试一个控制器。

    在我的解释中,这意味着您负责提供所有依赖项(例如,您可以提供模拟等)。而且由于您刚刚创建了没有任何依赖关系的新实例,因此您获得了 NPE。

    所以我看到了两个解决方案:

    1. 提供您自己的模拟依赖项

    2. 如果您希望 spring 为您解决依赖关系,请改用 webAppContextSetup.webAppContextSetup

    【讨论】:

    • 另外值得注意的是,这些天的建议是使用构造函数注入而不是自动装配字段。我发现采用这种方法的最大好处是,在测试中注入 mock 变得很简单。
    • 完美答案。还将研究构造函数注入。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 2017-07-17
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 1970-01-01
    相关资源
    最近更新 更多