Add app health check support to Dapr Testcontainer (#1213)

* Add app health check support to Dapr Testcontainer

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Some minor cleanup

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

* Move waiting to beforeEach, it looks more natural

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>

---------

Signed-off-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
This commit is contained in:
artur-ciocanu 2025-02-10 02:02:43 +02:00 committed by GitHub
parent 0cec586d35
commit 22d9874ae0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 25 additions and 13 deletions

View File

@ -23,16 +23,14 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Disabled;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
@ -56,8 +54,9 @@ public class DaprSpringMessagingIT {
private static final Logger logger = LoggerFactory.getLogger(DaprSpringMessagingIT.class);
private static final String TOPIC = "mockTopic";
private static final Network DAPR_NETWORK = Network.newNetwork();
private static final int APP_PORT = 8080;
private static final String SUBSCRIPTION_MESSAGE_PATTERN = ".*app is subscribed to the following topics.*";
@Container
@ServiceConnection
@ -65,7 +64,8 @@ public class DaprSpringMessagingIT {
.withAppName("messaging-dapr-app")
.withNetwork(DAPR_NETWORK)
.withComponent(new Component("pubsub", "pubsub.in-memory", "v1", Collections.emptyMap()))
.withAppPort(8080)
.withAppPort(APP_PORT)
.withAppHealthCheckPath("/ready")
.withDaprLogLevel(DaprLogLevel.DEBUG)
.withLogConsumer(outputFrame -> System.out.println(outputFrame.getUtf8String()))
.withAppChannelAddress("host.testcontainers.internal");
@ -78,16 +78,16 @@ public class DaprSpringMessagingIT {
@BeforeAll
public static void beforeAll(){
org.testcontainers.Testcontainers.exposeHostPorts(8080);
org.testcontainers.Testcontainers.exposeHostPorts(APP_PORT);
}
@BeforeEach
public void beforeEach() throws InterruptedException {
Thread.sleep(1000);
public void beforeEach() {
// Ensure the subscriptions are registered
Wait.forLogMessage(SUBSCRIPTION_MESSAGE_PATTERN, 1).waitUntilReady(DAPR_CONTAINER);
}
@Test
@Disabled("Test is flaky due to global state in the spring test application.")
public void testDaprMessagingTemplate() throws InterruptedException {
for (int i = 0; i < 10; i++) {
var msg = "ProduceAndReadWithPrimitiveMessageType:" + i;

View File

@ -33,7 +33,7 @@ public class TestRestController {
private static final Logger LOG = LoggerFactory.getLogger(TestRestController.class);
private final List<CloudEvent<String>> events = new ArrayList<>();
@GetMapping("/")
@GetMapping("/ready")
public String ok() {
return "OK";
}

View File

@ -68,6 +68,7 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
private DaprPlacementContainer placementContainer;
private String appName;
private Integer appPort;
private String appHealthCheckPath;
private boolean shouldReusePlacement;
/**
@ -116,6 +117,11 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
return this;
}
public DaprContainer withAppHealthCheckPath(String appHealthCheckPath) {
this.appHealthCheckPath = appHealthCheckPath;
return this;
}
public DaprContainer withConfiguration(Configuration configuration) {
this.configuration = configuration;
return this;
@ -173,7 +179,7 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
*/
public DaprContainer withComponent(Path path) {
try {
Map<String, Object> component = this.YAML_MAPPER.loadAs(Files.newInputStream(path), Map.class);
Map<String, Object> component = YAML_MAPPER.loadAs(Files.newInputStream(path), Map.class);
String type = (String) component.get("type");
Map<String, Object> metadata = (Map<String, Object>) component.get("metadata");
@ -233,12 +239,12 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
List<String> cmds = new ArrayList<>();
cmds.add("./daprd");
cmds.add("-app-id");
cmds.add("--app-id");
cmds.add(appName);
cmds.add("--dapr-listen-addresses=0.0.0.0");
cmds.add("--app-protocol");
cmds.add(DAPR_PROTOCOL.getName());
cmds.add("-placement-host-address");
cmds.add("--placement-host-address");
cmds.add(placementService + ":50005");
if (appChannelAddress != null && !appChannelAddress.isEmpty()) {
@ -251,6 +257,12 @@ public class DaprContainer extends GenericContainer<DaprContainer> {
cmds.add(Integer.toString(appPort));
}
if (appHealthCheckPath != null && !appHealthCheckPath.isEmpty()) {
cmds.add("--enable-app-health-check");
cmds.add("--app-health-check-path");
cmds.add(appHealthCheckPath);
}
if (configuration != null) {
cmds.add("--config");
cmds.add("/dapr-resources/" + configuration.getName() + ".yaml");