在Docker中,Spring Boot集成testing失败,但不在外面

也许有人可以帮助我。

我有一个用gradle执行的一些集成testing,如果在Windows主机(java oracle)或ubuntu(java oracle)vm中执行,它们都是绿色的。

testing1(testing阻塞15分钟):

@RunWith(SpringRunner.class) @SpringBootTest( classes = {CustomerApplication.class, NoSecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ActiveProfiles("test") @DirtiesContext public class UserProcessorsTest { private static final String EMAIL_ADDRESS = "example@gmail.com"; private static final String FIRST_NAME = "foo"; private static final String LAST_NAME = "bar"; @Autowired private UserChannel userChannel; @Autowired private CustomerChannel customerChannel; @Autowired private MessageCollector messageCollector; @MockBean private UserService userService; @MockBean private AccessToken accessToken; /** * When is received a event of type UserCreated a customer should be created */ @Test @SuppressWarnings("unchecked") public void customerCreatedAfterUserCreatedEvent() { String userId = UUID.randomUUID().toString(); given(this.userService.customerWith(userId)) .willReturn(Optional.of( new CustomerResource( FIRST_NAME, LAST_NAME, EMAIL_ADDRESS))); userChannel .userCreatedChannel() .send( MessageBuilder .withPayload(new UserCreated( Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()), userId, EMAIL_ADDRESS)).build()); Message<CustomerCreated> customerCreatedMessage = (Message<CustomerCreated>) messageCollector.forChannel(customerChannel.customerCreatedChannel()).poll(); CustomerCreated customerCreated = customerCreatedMessage.getPayload(); assertThat(customerCreated.getFirstName(), equalTo(FIRST_NAME)); assertThat(customerCreated.getLastName(), equalTo(LAST_NAME)); assertThat(customerCreated.getEmailAddress(), equalTo(EMAIL_ADDRESS)); } } 

保存客户的方法

  public Customer saveCustomer(String customerId, String emailAddress) { if (customerWithEmailAddress(emailAddress).isPresent()) { if (logger.isErrorEnabled()) { logger.error(String.format("Cannot save a customer already in the system %s", emailAddress)); } throw new IllegalStateException(); } Optional<CustomerResource> optionalCustomerResource = customerAdapter.customerWith(customerId); if (!optionalCustomerResource.isPresent()) { if (logger.isErrorEnabled()) { logger.error(String.format("Couldn't retrieve the customer %s", emailAddress)); } throw new ResourceNotFoundException(); } CustomerResource customerResource = optionalCustomerResource.get(); Customer customer = new Customer( new FullName( customerResource.getFirstName(), customerResource.getLastName()), new ContactInformation( new EmailAddress(customerResource.getEmailAddress())), securityNumberService.newSecurityNumber()); customerRepository.save(customer); publisher.publishEvent( new CustomerCreated( Date.from(customer.getCreatedAt().atZone(ZoneId.systemDefault()).toInstant()), customer.getFullName().getFirstName(), customer.getFullName().getLastName(), customer.getId(), customer.getContactInformation().getEmailAddress().getAddress())); return customer; } 

处理器保存后

  @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) public void handleCustomerCreatedEvent(CustomerCreated customerCreated) { if (logger.isInfoEnabled()) { logger.info(customerCreated.toString()); } customerCreatedChannel.send( MessageBuilder .withPayload(customerCreated) .build()); } 

testing2:

  public boolean validateSecurityNumberToken(String token, Long customerId) { Optional<SecurityNumberToken> optionalSecurityNumberToken = securityNumberTokenRepository.findByToken(token); if (!optionalSecurityNumberToken.isPresent()) { return false; } SecurityNumberToken securityNumberToken = optionalSecurityNumberToken.get(); // Fails HERE if (securityNumberToken.isTokenExpired() && securityNumberToken.getPetitioner().equals(customerId)) { securityNumberTokenRepository.delete(securityNumberToken); return false; } return true; } public boolean isTokenExpired() { return Instant.now().isAfter(expireOn); } 

使用的版本:

 dependencyManagement { imports { mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Finchley.M4' } 

}

用于运行testing的docker(也试用过gradle:jdk8)

 FROM gradle:jdk8-alpine RUN mkdir /home/gradle/source COPY gradle/ /home/gradle/source/gradle/ COPY src/ /home/gradle/source/src/ COPY build.gradle /home/gradle/source/build.gradle COPY gradle.properties /home/gradle/source/gradle.properties COPY settings.gradle /home/gradle/source/settings.gradle WORKDIR /home/gradle/source CMD ["gradle","--no-daemon","sonarqube"] 

总是有一个testing失败,我认为这个问题与时区有关(在启动时设置)。

另一个testing是基于SpringTransactional和@Cacheable的Spring Cloud Stream中的一个方法,问题是它在连续和通过之前被locking超过15分钟。

它被locking在这个方法中

 TransactionSynchronizationManager.doUnbindResource 

当删除这个方法

  @Cacheable(cacheNames = "customers", unless = "#result == null") public Optional<Customer> customerWithEmailAddress(String emailAddress) { return customerRepository .findCustomerWithEmailAddress(emailAddress); } 

docker – 撰写文件

 version: '3' services: customer-database: image: mysql:5.7 ports: - 3306:3306 environment: - MYSQL_ROOT_PASSWORD=customers - MYSQL_PASSWORD=customers - MYSQL_USER=customers - MYSQL_DATABASE=customers command: --default-time-zone='-03:00' customer-cache: image: redis:3.2 ports: - 6379:6379 customer-service-tests: container_name: customer-service-tests build: context: ./ dockerfile: Dockerfile.test volumes: - ~/.gradle:/home/gradle/.gradle/caches 

正如我所说,这只发生在docker集装箱内。

谢谢。