Replace integration test with test containers

This commit is contained in:
Dave Syer
2020-09-21 10:38:13 +01:00
parent 3115833c88
commit 3f490b7bcb
8 changed files with 82 additions and 183 deletions

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2019-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.demo;
import java.util.concurrent.TimeUnit;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.ToStringConsumer;
import org.testcontainers.utility.MountableFile;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Dave Syer
*
*/
// @Disabled
public class ContainerTests {
@Test
void test() throws Exception {
ToStringConsumer consumer = new ToStringConsumer();
try (@SuppressWarnings("resource")
GenericContainer<?> container = new GenericContainer<>("lambci/lambda:provided").withLogConsumer(consumer)
.withCopyFileToContainer(MountableFile.forClasspathResource("bootstrap"), "/var/task/")
.withEnv("DOCKER_LAMBDA_STAY_OPEN", "1").withExposedPorts(9001)) {
container.start();
int port = container.getFirstMappedPort();
String host = container.getHost();
System.err.println(host + ":" + port);
DemoApplication.main(new String[] { "--AWS_LAMBDA_RUNTIME_API=" + host + ":" + port, "--_HANDLER=foobar",
"--logging.level.org.springframework=DEBUG" });
ResponseEntity<String> response = Awaitility.waitAtMost(30, TimeUnit.SECONDS).until(() -> {
ResponseEntity<String> result = new RestTemplate().postForEntity(
"http://" + host + ":" + port + "/2015-03-31/functions/foobar/invocations",
"{\"name\":\"foo\"}", String.class);
return result;
}, result -> result != null);
assertThat(response.getBody()).contains("hi foo!");
assertThat(response.getHeaders()).containsKey("X-Amzn-Requestid");
}
String output = consumer.toUtf8String();
assertThat(output).contains("Lambda API listening on port 9001");
assertThat(output).contains("START RequestId:");
assertThat(output).contains("END RequestId:");
}
}

View File

@@ -1,55 +0,0 @@
package com.example.demo;
import com.example.test.TestServer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.function.context.test.FunctionalSpringBootTest;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.SocketUtils;
import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat;
@FunctionalSpringBootTest({"spring.cloud.function.web.export.source.url=http://localhost:${export.port}/home",
"spring.cloud.function.web.export.sink.url=http://localhost:${export.port}/echo",
"logging.level.reactor=OFF",
"logging.level.io.netty=OFF"})
public class DemoApplicationTests {
static ConfigurableApplicationContext context;
@Value("${export.port}")
private int port;
@Autowired
private WebClient.Builder builder;
@Test
public void contextLoads() throws Exception {
WebClient client = builder.baseUrl("http://localhost:" + port).build();
client.post().uri("/add").bodyValue("{\"name\":\"Fred\"}").exchange().block();
Thread.sleep(1000L);
String response = client.get().uri("/take").exchange().block().bodyToMono(String.class).block();
assertThat(response).isEqualTo("{\"name\":\"hi Fred!\"}");
}
@AfterAll
static void after() {
if (context != null) {
context.close();
}
}
@BeforeAll
static void before() {
int port = SocketUtils.findAvailableTcpPort();
System.setProperty("export.port", "" + port);
context = SpringApplication.run(TestServer.class, "--server.port="+port, "--spring.cloud.function.web.export.enabled=false", "--spring.main.web-application-type=reactive");
}
}

View File

@@ -1,85 +0,0 @@
package com.example.test;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.function.json.JsonMapper;
import org.springframework.context.annotation.Bean;
import reactor.core.publisher.Mono;
import reactor.core.publisher.MonoProcessor;
@SpringBootApplication(proxyBeanMethods = false)
public class TestServer {
private MonoProcessor<String> output = MonoProcessor.<String>create();
private String response = "";
public static void main(String[] args) {
Set<String> list = new LinkedHashSet<>(Arrays.asList(args));
list.addAll(Arrays.asList("--server.port=8000", "--spring.cloud.function.web.export.enabled=false", "--spring.main.web-application-type=reactive"));
SpringApplication.run(TestServer.class, list.toArray(new String[0]));
}
@Bean
public Supplier<Mono<String>> home() {
return () -> output;
}
// @Bean
// public Function<String, String> echo(JsonMapper mapper) {
// return input -> {
// response = input;
// return "Echo: " + response;
// };
// }
@Bean
public Function<Foo, String> echo(JsonMapper mapper) {
return input -> {
System.out.println("===> POJO " + input);
response = new String(mapper.toJson(input));
return "Echo: " + response;
};
}
@Bean
public Function<String, String> add() {
return input -> {
System.err.println("Add: " + input);
output.onNext(input);
output = MonoProcessor.<String>create();
return "Added: " + input;
};
}
@Bean
public Supplier<String> take() {
return () -> response;
}
}
class Foo {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Foo(String name) {
this.name = name;
}
Foo() {}
}

View File

@@ -0,0 +1,6 @@
#!/bin/sh
while true
do
sleep 1
done