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

在Spock测试中加载Spring上下文之前,如何启动嵌入式Cassandra服务器?

韦正业
2023-03-14

在我的一个集成测试中,我似乎遇到了一个棘手的问题。我有一个基于Spring Boot/Spring MVC的REST服务器和一个Cassandra DB。我使用spring数据cassandra jar文件,通过一个CrudRepository实现,通过CassandraTemplate将POJO插入到DB中。应用程序运行良好,我可以进行REST调用,框架可以将我的表单数据正确地转换为POJO,并将数据插入数据库。到目前为止,一切顺利。

我要做的是编写一个执行整个堆栈的集成测试。显然,我不想依赖外部DB,所以我使用了来自cassandra unit spring的EmbeddedCassandra东西,并通过了Spock测试。我遇到的问题似乎与@ContextConfiguration注释中定义的SpringApplicationContextLoader和@TestExecutionListener注释中定义的CassandraUnitTestExecutionListener类之间的某种排序冲突有关。由于这是一个Spock测试,它需要SpringApplicationContextLoader类来自动启动Spring Boot服务器。然而,它在Cassandra服务器启动之前就这样做了,这会导致集群/会话bean无法加载,因为它们显然试图在创建时立即联系服务器。我尝试了很多东西的组合,我的头都快晕过去了。我不得不求助于我认为非常丑陋的解决方案。我有一个setup()方法,它使用布尔值来确保上下文和Spring Boot应用程序只运行一次。我尝试将其放在每个测试类只运行一次的setupSpec()方法中,但没有成功(有些方法遇到了22个问题)。如果我尝试@Autowire上下文,那么它会在CassandraServer启动之前被注入。正如我所提到的,我已经尝试了无数不同的事情。

这个解决方案是可行的,但它让我感到困扰,因为我无法让它以更优雅的方式工作,只使用注释和DI。此外,@值注释字段没有初始化,这就是为什么我不得不在启动Tomcat后通过环境获取服务器端口的原因。任何关于如何以“正确的方式”做到这一点的建议都是非常受欢迎的。谢谢

@ActiveProfiles(profiles = ["test"])
@ContextConfiguration(loader = SpringApplicationContextLoader.class, classes = Application.class)
// @WebIntegrationTest("server.port:0") // Pick a random port for Tomcat
@EnableConfigurationProperties
@EmbeddedCassandra
@CassandraDataSet(value = ["cql/createUserMgmtKeySpace.cql", "cql/createUserMgmtTables.cql"], keyspace = "user_mgmt")
@TestExecutionListeners(listeners = [ CassandraUnitTestExecutionListener.class ]) //, DependencyInjectionTestExecutionListener.class ]) //, mergeMode = MergeMode.MERGE_WITH_DEFAULTS)
@Title("Integration test for the lineup ingestion REST server and the Cassandra DAOs.")
public class CassandraSpec extends Specification {
  @Shared
  ApplicationContext context
  @Shared
  CQLDataLoader cql
  @Shared boolean initialized = false

  // This is the server port that Spring picked. We use it in the REST URLs
  //  @Value('${local.server.port}')
  @Shared
  int serverPort

  def setup() {
    if (initialized) {
      return
    }

    System.setProperty("spring.profiles.active", "test")
    SpringApplication app = new SpringApplication(CassandraConfig.class)
    app.headless = true
    context = app.run(Application.class)
    assert context
    cql = new CQLDataLoader(context.getBean("session"))
    serverPort = Integer.parseInt(context.environment.getProperty('server.port'))
    println("Tomcat port: ${serverPort}")
    initialized = true
  }

... test methods here ...
}

共有2个答案

燕野
2023-03-14

上面由@user2337270提供的答案是正确的。虽然我没有使用Spock测试框架,但我花了相当多的时间试图让cassandra单元和Spring工作。添加CassandraUnitDependencyInjexiTestExecutionListener成功了。我认为提供一个有效的完整测试类的示例可能对其他用户有所帮助。希望它有帮助。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { CassandraConfig.class, InboundDocumentCassandraDaoTest.CassandraPropertiesTest.class })
@EmbeddedCassandra
@CassandraDataSet(value = {"idoc.cql"}, keyspace = "idoc")
@TestExecutionListeners(listeners = {     CassandraUnitDependencyInjectionTestExecutionListener.class,  DependencyInjectionTestExecutionListener.class  })
public class InboundDocumentCassandraDaoTest {

    @Autowired
    CassandraOperations cassOp;

    @Autowired
    InboundDocumentDao dao;

    @Test
    public void insert_into_idocs() throws Exception {

        UUID id = UUIDs.timeBased();
        long addedDate = System.currentTimeMillis();

        Insert insert = QueryBuilder.insertInto("idocs");
        insert.setConsistencyLevel(ConsistencyLevel.ONE);
        insert.value("idoc_id", id);
        insert.value("idoc_added_date", addedDate);
        insert.value("idoc_type", "invoice");
        insert.value("json_doc", "{ \"foo\":\"bar\" }");

        cassOp.execute(insert);

        String jsonObj = dao.getInboundDocumentById(id.toString());
        assertNotNull(jsonObj);
        assertEquals("{ \"foo\":\"bar\" }", jsonObj);
    }

    @Configuration
    public static class CassandraPropertiesTest {
        @Bean
        public CassandraProperties cassadraProps() {
            CassandraProperties props = new CassandraProperties();
            props.setCassandraContactpoints("127.0.0.1");
            props.setCassandraPort("9142");
            props.setCassandraKeyspace("idoc");
            props.setReadConsistencyLevel("LOCAL_ONE");
            return props;
        }
    }
}

仅供参考,idoc。cql文件被放置在src/main/resources文件夹中。

韶宏邈
2023-03-14

面掌!!!发布此内容后,我发现我需要添加CassandraUnitDependencyInjewTestExecutionListener。神奇的线条是:

@TestExecutionListeners(listeners = [ CassandraUnitDependencyInjectionTestExecutionListener, CassandraUnitTestExecutionListener, DependencyInjectionTestExecutionListener.class ]) 

在那之后,我能够在没有任何其他麻烦的情况下运行测试,并且可以注入一个临时端口并在RestTemplate URL中使用它。已解决问题:-)

 类似资料:
  • 我需要启动spring boot的嵌入式tomcat服务器,并在调试模式下启动服务器

  • 嗨,我有一个Spring Boot(2.1.6发行版)应用程序,我正在尝试添加一些简单的集成测试到我的应用程序。首先,我创建了一个基础IntegrationTest类,如下所示: 这是我的测试方法: 有什么建议吗?

  • 我需要启动一个嵌入式cassandra实例,通过单元测试在cassandra键空间上执行一些操作。编程语言是Java。启动嵌入式cassandra有哪些选项? 我使用了mojo maven插件,但是在使用以下命令启动实例之后,我没有看到cassandra实例在localhost上的默认端口9042启动。插件:http://www.mojohaus.org/cassandra-maven-plugi

  • 我使用Spock框架来运行我的测试。每个测试类上都有Spring的注释。正如我所看到的,每个测试类都需要上下文,在不同的类中运行几十个测试需要很多时间。是否有一种方法可以配置Spock测试类以在公共spring上下文下运行?

  • 运行Spring Boot应用程序时,嵌入式tomcat服务器无法启动。我刚刚在pom.xml中添加了所需的依赖项,并创建了一个简单的java POJO类。应用程序属性已经按照oracle数据库所需的jdbc配置以及Hibernate方言信息进行了设置。 执行mvn spring-boot:run时的控制台日志

  • 我想用Mock测试方法,没有spring上下文。我该怎么做?现在,变量返回null。我想设置方法的返回值。