Use Awaitility in our own tests

Closes gh-18227
This commit is contained in:
Andy Wilkinson
2019-09-12 15:50:53 +01:00
parent 568caa1206
commit 1b237de5f5
28 changed files with 403 additions and 348 deletions

View File

@@ -35,6 +35,11 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>

View File

@@ -20,11 +20,9 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.time.Duration;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
@@ -39,7 +37,7 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.util.StreamUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.containsString;
/**
* Basic integration tests for service demo application.
@@ -66,8 +64,7 @@ class SampleIntegrationApplicationTests {
"--service.output-dir=" + outputDir);
SpringApplication.run(ProducerApplication.class, "World", "--service.input-dir=" + inputDir,
"--service.output-dir=" + outputDir);
String output = getOutput(outputDir);
assertThat(output).contains("Hello World");
awaitOutputContaining(outputDir, "Hello World");
}
@Test
@@ -76,41 +73,35 @@ class SampleIntegrationApplicationTests {
File outputDir = new File(temp.toFile(), "output");
this.context = SpringApplication.run(SampleIntegrationApplication.class, "testviamg",
"--service.input-dir=" + inputDir, "--service.output-dir=" + outputDir);
String output = getOutput(this.context.getBean(ServiceProperties.class).getOutputDir());
assertThat(output).contains("testviamg");
awaitOutputContaining(this.context.getBean(ServiceProperties.class).getOutputDir(), "testviamg");
}
private String getOutput(File outputDir) throws Exception {
Future<String> future = Executors.newSingleThreadExecutor().submit(new Callable<String>() {
@Override
public String call() throws Exception {
Resource[] resources = getResourcesWithContent(outputDir);
while (resources.length == 0) {
Thread.sleep(200);
resources = getResourcesWithContent(outputDir);
}
StringBuilder builder = new StringBuilder();
for (Resource resource : resources) {
try (InputStream inputStream = resource.getInputStream()) {
builder.append(new String(StreamUtils.copyToByteArray(inputStream)));
}
}
return builder.toString();
}
});
return future.get(30, TimeUnit.SECONDS);
private void awaitOutputContaining(File outputDir, String requiredContents) throws Exception {
Awaitility.waitAtMost(Duration.ofSeconds(30)).until(() -> outputIn(outputDir),
containsString(requiredContents));
}
private Resource[] getResourcesWithContent(File outputDir) throws IOException {
Resource[] candidates = ResourcePatternUtils.getResourcePatternResolver(new DefaultResourceLoader())
.getResources("file:" + outputDir.getAbsolutePath() + "/**");
for (Resource candidate : candidates) {
if ((candidate.getFilename() != null && candidate.getFilename().endsWith(".writing"))
|| candidate.contentLength() == 0) {
return new Resource[0];
private String outputIn(File outputDir) throws IOException {
Resource[] resources = findResources(outputDir);
if (resources.length == 0) {
return null;
}
return readResources(resources);
}
private Resource[] findResources(File outputDir) throws IOException {
return ResourcePatternUtils.getResourcePatternResolver(new DefaultResourceLoader())
.getResources("file:" + outputDir.getAbsolutePath() + "/*.txt");
}
private String readResources(Resource[] resources) throws IOException {
StringBuilder builder = new StringBuilder();
for (Resource resource : resources) {
try (InputStream input = resource.getInputStream()) {
builder.append(new String(StreamUtils.copyToByteArray(input)));
}
}
return candidates;
return builder.toString();
}
}

View File

@@ -29,6 +29,11 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka-test</artifactId>

View File

@@ -15,6 +15,9 @@
*/
package smoketest.kafka;
import java.time.Duration;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -22,6 +25,8 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.kafka.test.context.EmbeddedKafka;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.not;
/**
* Integration tests for demo application.
@@ -39,10 +44,7 @@ class SampleKafkaApplicationTests {
@Test
void testVanillaExchange() throws Exception {
long end = System.currentTimeMillis() + 10000;
while (this.consumer.getMessages().isEmpty() && System.currentTimeMillis() < end) {
Thread.sleep(250);
}
Awaitility.waitAtMost(Duration.ofSeconds(30)).until(this.consumer::getMessages, not(empty()));
assertThat(this.consumer.getMessages()).extracting("message").containsOnly("A simple test message");
}

View File

@@ -34,6 +34,11 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>

View File

@@ -20,7 +20,9 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.time.Duration;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import smoketest.parent.SampleParentContextApplication;
@@ -33,7 +35,7 @@ import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.util.StreamUtils;
import static org.junit.jupiter.api.Assertions.fail;
import static org.hamcrest.Matchers.containsString;
/**
* Basic integration tests for service demo application.
@@ -65,26 +67,16 @@ class SampleIntegrationParentApplicationTests {
}
private void awaitOutputContaining(File outputDir, String requiredContents) throws Exception {
long endTime = System.currentTimeMillis() + 30000;
String output = null;
while (System.currentTimeMillis() < endTime) {
Resource[] resources = findResources(outputDir);
if (resources.length == 0) {
Thread.sleep(200);
resources = findResources(outputDir);
}
else {
output = readResources(resources);
if (output != null && output.contains(requiredContents)) {
return;
}
else {
Thread.sleep(200);
output = readResources(resources);
}
}
Awaitility.waitAtMost(Duration.ofSeconds(30)).until(() -> outputIn(outputDir),
containsString(requiredContents));
}
private String outputIn(File outputDir) throws IOException {
Resource[] resources = findResources(outputDir);
if (resources.length == 0) {
return null;
}
fail("Timed out awaiting output containing '" + requiredContents + "'. Output was '" + output + "'");
return readResources(resources);
}
private Resource[] findResources(File outputDir) throws IOException {

View File

@@ -35,6 +35,11 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>

View File

@@ -16,6 +16,9 @@
package smoketest.quartz;
import java.time.Duration;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -24,7 +27,7 @@ import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.context.ConfigurableApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.containsString;
/**
* Tests for {@link SampleQuartzApplication}.
@@ -37,11 +40,7 @@ class SampleQuartzApplicationTests {
@Test
void quartzJobIsTriggered(CapturedOutput output) throws InterruptedException {
try (ConfigurableApplicationContext context = SpringApplication.run(SampleQuartzApplication.class)) {
long end = System.currentTimeMillis() + 5000;
while ((!output.toString().contains("Hello World!")) && System.currentTimeMillis() < end) {
Thread.sleep(100);
}
assertThat(output).contains("Hello World!");
Awaitility.waitAtMost(Duration.ofSeconds(5)).until(output::toString, containsString("Hello World!"));
}
}