Java 使用Spring数据的单元/集成测试&;MongoDB无法模拟存储库

Java 使用Spring数据的单元/集成测试&;MongoDB无法模拟存储库,java,spring,mongodb,unit-testing,spring-mvc,Java,Spring,Mongodb,Unit Testing,Spring Mvc,一些小信息: 这不是关于端到端的测试,而是指现在使用多个模块进行的集成测试 由于之前的一些困难,我们不得不更改很多测试代码,我正在努力降低集成级别,以便我们回到单元测试。然而,在我被允许减少配置等之前,我需要首先让所有的东西都重新工作 如果你读了最后一段,你已经知道了,但不管怎样:我知道这不是一个好的方法,我正在努力改变它,但是我必须先这样做 依赖关系 弹簧靴1.3.0 Spring Mongo 1.3.3 Spring Security 3.1.4 弹簧安全Cas 4.0.2 活板门嵌入M

一些小信息:

  • 这不是关于端到端的测试,而是指现在使用多个模块进行的集成测试
  • 由于之前的一些困难,我们不得不更改很多测试代码,我正在努力降低集成级别,以便我们回到单元测试。然而,在我被允许减少配置等之前,我需要首先让所有的东西都重新工作
  • 如果你读了最后一段,你已经知道了,但不管怎样:我知道这不是一个好的方法,我正在努力改变它,但是我必须先这样做
依赖关系 弹簧靴1.3.0
Spring Mongo 1.3.3
Spring Security 3.1.4
弹簧安全Cas 4.0.2
活板门嵌入Mongo 1.46.0

基础 现在,我们有一个抽象测试类,用

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(TestConfig.class)
@WebAppConfiguration

TestConfig类如下所示:

@Configuration
@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
@ComponentScan(value = { "package1", "package2" })
public class TestConfig {

}
如您所见,它扫描这两个包中的所有内容,并获取其他几个配置类:

@Configuration
// needed if working with Spring-Data-Repository interfaces and subprojects
// http://stackoverflow.com/questions/29084824/spring-repository-components-not-found-in-gradle-subproject-springboot
@EnableMongoRepositories({ "package2.subpackage" })
public class ModelConfiguration {

}

这是我测试课程的一部分:

@SpringApplicationConfiguration(classes = TestClass.TestConfiguration.class)
public class TestClass extends AbstractTest {

    @Order(Ordered.HIGHEST_PRECEDENCE)
    public static class TestConfiguration {
        @Bean
        @Primary
        public FooRepository fooRepository() {
            FooRepository mock = mock(FooRepository.class);
            // mockbehaviour
            return mock;
        }

        @Bean
        @Primary
        public FooDao fooDao() {
            FooDao mock = mock(FooDao.class);
            //Mock behaviour
            return mock;
        }

        @Bean
        @Primary
        public BarDao barDao() {
            BarDao mock = mock(BarDao.class);
            //MockBehaviour
            return mock;
        }

        @Bean
        @Primary
        public BarRepository barRepository() {
            BarRepository mock = mock(BarRepository.class);
            return mock;
        }
    }
我现在创建了几个请求,这些请求被传递给超类进行安全测试,并且(因为所有测试都只有一个成功案例),然后我尝试通过verify(mock)验证对DAO和存储库的相应调用

bean通过
@Resource
注入控制器,与我在测试类中使用它们的方式相同

问题 出于某种原因,DAO正在按预期工作(创建、指定行为、调用并可以验证),存储库没有-创建并使用常规代理。在使用
@Order(Ordered.HIGHEST_priority)
之前,只需跳过bean的创建(并以这样的方式记录),因为已注册的顶级bean被拒绝覆盖

在采用这种方法之后,存储库bean被覆盖而不是被跳过(当然,也被记录下来)。bean级别的
@Primary
应该确保使用模拟,而不是组件扫描创建的实际bean——以及其他测试实例,它们不会启动整个应用程序和嵌入式Mongo,这是预期的——但在这里,它没有

我尝试过的事情
  • 设置
    @Order
  • 排除
    @enablemongorepositions
    -配置
  • 手动注入创建的模拟
  • 彻底的网络研究
  • 设置bean角色
  • 重新触发bean的创建
  • 在创建DAOBean时触发bean创建

我已经找了好几天了,一直以来,我偶然发现的唯一可能的解决方案是:创建一个xml配置(这是一个禁忌,因为我们应该在不需要xml文件的情况下创建所有内容),使用Fongo(这需要为这一步导入一个新的依赖项,因为数据库测试完全在其他地方进行,然后将其删除),或者禁用bean重写(我完全不知道该怎么做,Spring文档也没有真正的帮助-是的,方法是存在的,但每当我尝试这样做时,它都不会影响当前上下文)。

很抱歉,这更适合注释而不是答案,但格式太糟糕了

不知道为什么它不起作用,但是您是否尝试使用@Configuration bean的显式导入,而不是使用ComponenScan

e、 g:


通过这种方式,您可以控制配置加载的顺序。

您能为org.springframework提供调试级别的日志集吗?@frant.hartm是的,但我不想发布整个日志-如果您能给我一个关于您要查找的内容的提示,我将很乐意发布。然而,我看到,在我的bean正常加载之后,SpringData mongoBD正在注册自己的存储库,然后扫描FooRepositoryImpl.class(soed不存在),之后,它只是用自己的文件覆盖已经注册的FooRepository。我没有尝试这样做,因为我们几乎所有的组件(存储库、DAO、控制器等)由componentScan加载。另外,我认为顺序在这里并不重要-如果我的配置在mongo之后加载,我的repositorybean就会被跳过,如果它在mongo之前加载,它就会被覆盖。完全去掉componentScan可以确保我的模拟被创建,但是嵌入式mongo不会启动,或者我们的sec不会启动urity上下文无法正确加载(因此禁止每个请求)有趣的是,经过长时间的操作后,我们找到了罪魁祸首。其他人已经尝试创建了测试,这是,他的类被
@Configuration
注释,但没有在相应的包中。这个类有
@EnableAutoConfiguration
而没有明确排除
EmbeddedMongoutoconfiguration
w这就是我们重写repositorymocks的原因。在去掉它之后,通过向每个类添加单独的测试配置来确保配置是测试独占的,我们使它工作了。因此感谢您的建议=)
@SpringApplicationConfiguration(classes = TestClass.TestConfiguration.class)
public class TestClass extends AbstractTest {

    @Order(Ordered.HIGHEST_PRECEDENCE)
    public static class TestConfiguration {
        @Bean
        @Primary
        public FooRepository fooRepository() {
            FooRepository mock = mock(FooRepository.class);
            // mockbehaviour
            return mock;
        }

        @Bean
        @Primary
        public FooDao fooDao() {
            FooDao mock = mock(FooDao.class);
            //Mock behaviour
            return mock;
        }

        @Bean
        @Primary
        public BarDao barDao() {
            BarDao mock = mock(BarDao.class);
            //MockBehaviour
            return mock;
        }

        @Bean
        @Primary
        public BarRepository barRepository() {
            BarRepository mock = mock(BarRepository.class);
            return mock;
        }
    }
@SpringApplicationConfiguration(classes = TestClass.TestConfiguration.class)
public class TestClass extends AbstractTest {

    @Configuration
    @Import( TestConfig.class )
    public static class TestConfiguration {
       //...
    }
}

@Configuration
@EnableAutoConfiguration(exclude = { EmbeddedMongoAutoConfiguration.class })
// @ComponentScan(value = { "package1", "package2" }) // GET RID OF THIS
@Import( { TestMongoConfiguration.class /*, OtherConfig.class, ... */ } )
public class TestConfig {

}