当前位置: 首页 > 知识库问答 >
问题:

在应用程序运行期间加载到Spring上下文中的测试配置bean

后焕
2023-03-14

我正在开发一个spring boot(V2.2.4)应用程序,专门添加集成测试,该测试利用Testcontainers实例化一个docker容器,该容器运行一个Postgres实例进行测试,以对其执行数据库事务。这些测试通过Liquibase将我们的数据库模式推送到Postgres实例中。我是按照这个指南实现的。到测试时Postgres的连接由一个名为TestPostgresConfig的类管理。java(见下文)。liquibase操作由同一类中定义的SpringLiquibase对象执行。我在成功构建应用程序后尝试运行应用程序时遇到问题。问题是Spring上下文试图在运行时实例化SpringLiquibase bean(由于找不到db.changelog-master.yaml而失败),我不希望它这样做:

警告[main]组织。springframework。上下文支持AbstractApplicationContext:在上下文初始化期间遇到异常-取消刷新尝试:org。springframework。豆。工厂BeanCreationException:

创建在类路径资源中定义了名为“liquibase”的bean时出错

[org/spring框架/引导/自动配置/liquibase/LiquibasAutoConfiguration$LiquibasConfiguration.class]:调用init方法失败;嵌套异常liquibase.exception.ChangeLogParseExc0019:错误解析类路径: db/Changelog/changelog-master.yaml

因为java。伊奥。FileNotFoundException类路径资源[db/changelog/changelog master.yaml]无法解析为URL,因为它不存在

这个文件不存在,也永远不会存在于这个项目中,而liquibase首先不应该试图在运行时推送更改日志。我需要帮助弄清楚为什么Spring会尝试加载liquibase bean,以便在运行时避免这种情况发生。

我的设置:

@SpringBootApplication
@EnableRetry
@EnableCommonModule
@EnableScheduling
@Slf4j
@EnableConfigurationProperties({
    ExternalProperties.class,
    ApplicationProperties.class
})
public class MyApplication implements WebMvcConfigurer, CommandLineRunner {

    @Autowired
    MyService myService;

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    public void run(String... args) throws Exception {
        myService.doSomething();        
    }
}

TestPostgresConfig。爪哇:

@TestConfiguration
@Profile("integration")
public class TestPostgresConfig {

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName("org.postgresql.Driver");
        ds.setUrl(format("jdbc:postgresql://%s:%s/%s", MyIT.psqlContainer.getContainerIpAddress(),
                MyIT.psqlContainer.getMappedPort(5432), MyIT.psqlContainer.getDatabaseName()));
        ds.setUsername(MyIT.psqlContainer.getUsername());
        ds.setPassword(MyIT.psqlContainer.getPassword());
        ds.setSchema(MyIT.psqlContainer.getDatabaseName());
        return ds;
    }

    @Bean
    public SpringLiquibase springLiquibase(DataSource dataSource) throws SQLException {
        tryToCreateSchema(dataSource);
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDropFirst(true);
        liquibase.setDataSource(dataSource);
        liquibase.setDefaultSchema("the_schema");
        // This and all supported liquibase changelog files are copied onto my classpath 
        // via the maven assembly plugin. The config to do this has been omitted for the
        // sake of brevity
        // see this URL for how I did it:
        // https://blog.sonatype.com/2008/04/how-to-share-resources-across-projects-in-maven/
        liquibase.setChangeLog("classpath:/test/location/of/liquibase.changelog-root.yml");
        return liquibase;
    }
    
    private void tryToCreateSchema(DataSource dataSource) throws SQLException {
        String CREATE_SCHEMA_QUERY = "CREATE SCHEMA IF NOT EXISTS test";
        dataSource.getConnection().createStatement().execute(CREATE_SCHEMA_QUERY);
    }
}

我的。爪哇:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=CommonConfig.class)
@ActiveProfile("integration")
@Import(TestPostgresConfig.class)
public class MyIT {

    @ClassRule
    public static PostgreSQLContainer psqlContainer = new PostgreSQLContainer("postgres:13.1")
        .withDatabseName("test-database-instance")
        .withUsername("divdiff")
        .withPassword("theseAreNotTheDroidsForYou123");

    @BeforeClass
    public static void init() {
        System.setProperty("spring.datasource.url", "jdbc:postgresql://" 
            + psqlContainer.getHost() + ":"
            + psqlContainer.getMappedPort(5432) + "/"
            + psqlContainer.getDatabaseName()));
            System.setProperty("spring.datasource.username", psqlContainer.getUsername());
            System.setProperty("spring.datasource.password", psqlContainer.getPassword());
    }

    @Before
    public void setUp() {
        // code to set up my test
    }
    

    @Test
    public void testMyCodeEndToEnd() {
        // my test implementation
    }
}

MyConfig。爪哇:

@Configuration
@ComponentScan(basePackages = "my.code")
@EntityScan("my.code")
@Slf4j
public class MyConfig {

    @Bean
    public KeyStore keyStore() {
        //load keystore and set javax.net.ssl.keystore* properties
    }

    @Bean
    public KeyStore trustStore() {
        //load truststore and set javax.net.ssl.truststore* properties
    }

    @Bean
    public RestTemplate restTemplate() {
        //Set up and load SSL Context with key and trust store
        //Create HTTPClient and connection stuff
        //Look at this link for a similar set up 
        //https://www.baeldung.com/rest-template
    }
}

应用集成。yml

spring:
    jpa:
        properties:
            hibernate:
                enable_lazy_load_no_trans: true
    profiles:
        active: default

server:
    ssl:
        # My key and trust store values 

application: 
    unrelated-app-properties: 
        # propertie values below

包结构:

app project/src/main/java/com/my/code/MyApplication。JAVA

app project/src/main/java/com/my/code/service/MyService。JAVA

App-project/src/test/java/my/code/OTHER-TEST-CLASSES-LIVE-这里...

app project/src/test/java/integration/MyIT。JAVA

app project/src/test/java/integration/TestPostgresConfig。JAVA

app project/src/test/resources/application integration。yml

my-contion-project/src/main/java/通用/配置/MyConfig.java

非常感谢你的帮助!!!:D

共有1个答案

百里星纬
2023-03-14

您可以玷污液化石基上下文作为测试

<changeSet author="name" id="id-of-file" context="test">

并且有一个应用程序属性,比如:spring。液化。上下文=测试

然后加入一个液化豆子,比如:

@value("${spring.liquibase.contexts}")私有字符串liquibasContext;

@Bean
    public SpringLiquibase liquibase() {
        
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDataSource(localDatabaseDataSource);
        liquibase.setShouldRun(liquibaseEnabled);
        liquibase.setChangeLog(localDatabaseLiquibaseChangeLog);
        liquibase.setContexts(liquibaseContexts);
        return liquibase;
    }
 类似资料:
  • 我在我的src/test/resources路径中创建了一个application-integrationtest.yaml,所以我的测试是针对创建的docker TestContainer运行的。问题是没有加载我的application-integrationtest.yaml。 我正在运行一个SpringBoot2.x应用程序 原因:org.springframework.beans.Bean

  • 我得到的错误是: 我试图更改上下文配置的位置,如下所示:

  • 嗨,我正试图让spring junit测试用例...我要求加载完整的应用程序上下文。但是,junit测试不会初始化完整的应用程序上下文。 因此,它应该扫描com.test包中的所有spring bean,并将它们加载到Junit TestCase的applicationcontext中。但从大豆的产量来看,它似乎没有做到这一点。

  • 问题内容: 我有一个包含2个测试的测试类: 当我单独运行测试时,我不会出错,但是当我同时运行所有测试时,会失败。失败是由于某些测试修改了应用程序上下文导致的: 是否可以单独运行此测试?我只想在启动test1时读取所有必需的东西,然后运行测试,然后关闭所有必需的东西。然后启动test2。 问题答案: 您可以在修改应用程序上下文的测试类上使用@DirtiesContext批注。 Java文档 Spri

  • 我正在处理一个Spring Boot应用程序,其中我使用该应用程序公开SOAP WebService。我在Spring boot应用程序中使用Apache CFX framework for SOAP impl。我正在使用基于注释的方法。 我在一个bean中的Spring Boot配置文件中设置应用程序上下文时遇到了问题。下面是我的代码。 配置文件如下所示。 现在我有了bean SOAPproce

  • 问题内容: 我的WEB-INF目录下有一些XML文件: lyricsBaseApp-servlet.xml hibernate.xml dataSource.xml beans.xml servlet xml导入其他xml文件: 我希望我的junit4 类包含整个spring配置。使用默认文件名,我创建了一个文件。最后,我不知道该放在哪里… 我试过了: 要么 和其他一些想法,但都失败了。有人可以指