我有一个使用 SQLite 的 Micronaut 应用程序,我使用 groovy 和 Spock 为应用程序创建了集成测试。如果规范独立运行,一切正常,当所有测试同时运行时,有时使用 CrudRepository 的测试之一会失败并出现错误:
Error instantiating bean of type [io.micronaut.http.server.codec.TextStreamCodec]
Message:
Bean of type [class io.micronaut.context.DefaultApplicationContext$RuntimeConfiguredEnvironment]
is a manually registered singleton that was registered with the context via
BeanContext.registerBean(..) and cannot be created directly
Path Taken:
new DefaultJdbcRepositoryOperations(String dataSourceName,DataJdbcConfiguration jdbcConfiguration,DataSource dataSource,TransactionOperations transactionOperations,ExecutorService executorService,BeanContext beanContext,List codecs,DateTimeProvider dateTimeProvider,RuntimeEntityRegistry entityRegistry,DataConversionService conversionService,AttributeConverterRegistry attributeConverterRegistry,SchemaTenantResolver schemaTenantResolver,JdbcSchemaHandler schemaHandler)
--> new DefaultJdbcRepositoryOperations(String dataSourceName,DataJdbcConfiguration jdbcConfiguration,DataSource dataSource,TransactionOperations transactionOperations,ExecutorService executorService,BeanContext beanContext,[List codecs],DateTimeProvider dateTimeProvider,RuntimeEntityRegistry entityRegistry,DataConversionService conversionService,AttributeConverterRegistry attributeConverterRegistry,SchemaTenantResolver schemaTenantResolver,JdbcSchemaHandler schemaHandler)
--> new TextStreamCodec(ApplicationConfiguration applicationConfiguration,[ByteBufferFactory byteBufferFactory],BeanProvider codecRegistryProvider,CodecConfiguration codecConfiguration)
这是我所有规范的基类:
abstract class BaseSpec extends Specification {
@Shared
@Inject
protected EmbeddedServer embeddedServer
@AutoCleanup
@Shared
protected ApplicationContext applicationContext
@AutoCleanup("shutdown")
@Shared
protected WireMockServer wireMockServer
@SuppressWarnings("unused")
void setupSpec() {
//Thread.sleep(500)
preSetupSpec()
cleanDatabase()
WireMock.configureFor("localhost", 8090)
wireMockServer = new WireMockServer(options().port(8090))
wireMockServer.start()
Unirest.setHttpClient(HttpClientBuilder.create()
.setConnectionManager(new BasicHttpClientConnectionManager())
.build())
Unirest.setObjectMapper(new com.mashape.unirest.http.ObjectMapper() {
private ObjectMapper objectMapper = new ObjectMapper();
@Override
<T> T readValue(String value, Class<T> valueType) {
return objectMapper.readValue(value, valueType)
}
@Override
String writeValue(Object value) {
return objectMapper.writeValueAsString(value);
}
})
embeddedServer = ApplicationContext.run(EmbeddedServer, "integration")
applicationContext = embeddedServer.applicationContext
ApplicationSettings.BASE_URL = embeddedServer.URL.toString()
ApplicationSettings.PORT = embeddedServer.URL.getPort()
postSetupSpec()
}
protected void preSetupSpec() {}
protected void postSetupSpec() {}
private static void cleanDatabase() {
def parent = System.getProperty("user.dir")
new File(parent, "build/tmp/colleague-identity-distributed.db").delete()
}
@SuppressWarnings("unused")
void cleanupSpec() {
wireMockServer.stop()
}
void setup() {
if (!wireMockServer.isRunning()) {
wireMockServer.start()
}
wireMockServer.resetAll()
}
@SuppressWarnings("unused")
void stubEndpoint(StubMapping stubMapping) {
wireMockServer.addStubMapping(stubMapping)
}
}
并非总是相同的方法会失败,有趣的是,如果我只注释掉其中一个数据库测试(甚至不是失败的那个),一切都会恢复正常,似乎我超出了某种阈值。此外,在 setupSpec 的开头添加 Thread.sleep 可以解决问题。