我正在尝试在测试容器中使用 postgres 进行集成测试,由于缺少序列,它在 JUnit 执行期间抛出错误。
我试过不指定生成器,但由于找不到 hiberate_sequence 而失败。这在生产中有效(命名生成器)所以我很确定这不是一个简单的语法问题。
对可能导致错误的原因有什么建议吗?
更新
我创建了一个没有 Testcontainers 的新测试,它使用现有数据库,表和生成器已经在模式中。该测试是绿色的。用于创建表和生成器的 SQL 是 Spring 生成的 SQL。
环境:Spring Boot v2.7.8、postgres 12、testcontainers 1.17.6、JUnit 5、Java 11
简单的例子
@Builder(toBuilder = true)
@Entity
@Table(name = "motor")
public class MotorImpl implements Motor, Serializable {
private static final long serialVersionUID = -8719527647178838271L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "motor_generator")
@SequenceGenerator(name = "motor_generator", sequenceName = "motor_id_seq", allocationSize = 1)
private Long id;
@Version
private Integer version;
private String name;
// getters, setters, constructors generated by lombok
}
JUnit5测试类
@SpringBootTest
@Testcontainers
class MotorRepositoryTest {
@Container
private static final PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:12");
@DynamicPropertySource
static void registerPostgresProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired
MotorRepository repo;
@Test
@Transactional
void givenValidMotor_whenInsert_thenRecordCreated() {
MotorImpl m = MotorImpl.builder().build();
MotorImpl m_saved = repo.save(m);
assertNotNull(m_saved.getId());
Optional<MotorImpl> m_retrieved = repo.findById(m_saved.getId());
assertTrue(m_retrieved.isPresent());
}
}
从 Spring 捕获的自动 DDL
create sequence motor_id_seq start 1 increment 1;
create table motor (
id int8 not null,
name varchar(255),
status int4,
version int4,
primary key (id)
);
控制台日志
14:31:24.410 [main] INFO org.springframework.test.context.transaction.TransactionContext - Began transaction (1) for test context [DefaultTestContext@2681185e testClass = MotorRepositoryTest, testInstance = com.vogelware.testcontainer.motor.impl.MotorRepositoryTest@41f5389f, testMethod = givenValidMotor_whenInsert_thenRecordCreated@MotorRepositoryTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@3a012678 testClass = MotorRepositoryTest, locations = '{}', classes = '{class com.vogelware.testcontainer.TestcontainerApplication}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@2c4d1ac, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@41e68d87, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@24ba9639, org.springframework.boot.test.autoconfigure.actuate.metrics.MetricsExportContextCustomizerFactory$DisableMetricExportContextCustomizer@4331d187, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@335b5620, org.springframework.test.context.support.DynamicPropertiesContextCustomizer@513b5eb, org.springframework.boot.test.context.SpringBootTestArgs@1, org.springframework.boot.test.context.SpringBootTestWebEnvironment@3c153a1], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.event.ApplicationEventsTestExecutionListener.recordApplicationEvents' -> false]]; transaction manager [org.springframework.orm.jpa.JpaTransactionManager@69cb134]; rollback [true]
14:31:24.562 [main] DEBUG org.hibernate.SQL -
select
nextval ('motor_id_seq')
14:31:24.573 [main] WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 0, SQLState: 42P01
14:31:24.573 [main] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ERROR: relation "motor_id_seq" does not exist
Position: 17
我认为这是因为你的 spring.datasource.url 没有设置正确。 您必须在 jdbc Url 中指定 currentSchema。
类似的东西:
registry.add("spring.datasource.url",
() -> String.format("jdbc:postgresql://%s:%d/db064d10?currentSchema=test", databaseContainer.getContainerIpAddress(), databaseContainer.getMappedPort(5432)));