Skip to content

Commit f5ef43c

Browse files
committed
Create project: spring-cloud-azure-testcontainers-for-service-bus-spring-messaging-sample
1 parent 425be02 commit f5ef43c

3 files changed

Lines changed: 309 additions & 0 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns="http://maven.apache.org/POM/4.0.0"
5+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
6+
<modelVersion>4.0.0</modelVersion>
7+
8+
<parent>
9+
<groupId>org.springframework.boot</groupId>
10+
<artifactId>spring-boot-starter-parent</artifactId>
11+
<version>4.0.3</version>
12+
<relativePath/> <!-- lookup parent from repository -->
13+
</parent>
14+
15+
<groupId>com.azure.spring</groupId>
16+
<artifactId>spring-cloud-azure-testcontainers-for-service-bus-spring-messaging-sample</artifactId>
17+
<version>1.0.0</version>
18+
<packaging>jar</packaging>
19+
20+
<properties>
21+
<version.spring.cloud.azure>7.1.0-beta.1</version.spring.cloud.azure>
22+
</properties>
23+
24+
<dependencyManagement>
25+
<dependencies>
26+
<dependency>
27+
<groupId>com.azure.spring</groupId>
28+
<artifactId>spring-cloud-azure-dependencies</artifactId>
29+
<version>${version.spring.cloud.azure}</version>
30+
<type>pom</type>
31+
<scope>import</scope>
32+
</dependency>
33+
</dependencies>
34+
</dependencyManagement>
35+
36+
<dependencies>
37+
<dependency>
38+
<groupId>com.azure.spring</groupId>
39+
<artifactId>spring-messaging-azure-servicebus</artifactId>
40+
</dependency>
41+
<dependency>
42+
<groupId>com.azure.spring</groupId>
43+
<artifactId>spring-cloud-azure-starter</artifactId>
44+
</dependency>
45+
<dependency>
46+
<groupId>org.springframework.boot</groupId>
47+
<artifactId>spring-boot-starter-test</artifactId>
48+
<scope>test</scope>
49+
</dependency>
50+
<dependency>
51+
<groupId>org.springframework.boot</groupId>
52+
<artifactId>spring-boot-testcontainers</artifactId>
53+
<scope>test</scope>
54+
</dependency>
55+
<dependency>
56+
<groupId>org.testcontainers</groupId>
57+
<artifactId>azure</artifactId>
58+
<version>1.21.3</version>
59+
<scope>test</scope>
60+
</dependency>
61+
<dependency>
62+
<groupId>org.testcontainers</groupId>
63+
<artifactId>junit-jupiter</artifactId>
64+
<version>1.21.3</version>
65+
<scope>test</scope>
66+
</dependency>
67+
<dependency>
68+
<groupId>com.azure.spring</groupId>
69+
<artifactId>spring-cloud-azure-testcontainers</artifactId>
70+
<scope>test</scope>
71+
</dependency>
72+
<dependency>
73+
<groupId>com.microsoft.sqlserver</groupId>
74+
<artifactId>mssql-jdbc</artifactId>
75+
<scope>test</scope>
76+
</dependency>
77+
</dependencies>
78+
79+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import com.azure.messaging.servicebus.ServiceBusMessage;
2+
import com.azure.messaging.servicebus.ServiceBusSenderClient;
3+
import com.azure.spring.cloud.autoconfigure.implementation.context.AzureGlobalPropertiesAutoConfiguration;
4+
import com.azure.spring.cloud.autoconfigure.implementation.servicebus.AzureServiceBusAutoConfiguration;
5+
import com.azure.spring.cloud.autoconfigure.implementation.servicebus.AzureServiceBusMessagingAutoConfiguration;
6+
import com.azure.spring.cloud.autoconfigure.implementation.servicebus.properties.AzureServiceBusConnectionDetails;
7+
import com.azure.spring.cloud.service.servicebus.consumer.ServiceBusErrorHandler;
8+
import com.azure.spring.cloud.service.servicebus.consumer.ServiceBusRecordMessageListener;
9+
import com.azure.spring.messaging.servicebus.core.ServiceBusTemplate;
10+
import org.junit.jupiter.api.Test;
11+
import org.springframework.beans.factory.annotation.Autowired;
12+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
13+
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
14+
import org.springframework.context.annotation.Bean;
15+
import org.springframework.context.annotation.Configuration;
16+
import org.springframework.messaging.support.MessageBuilder;
17+
import org.springframework.test.context.TestPropertySource;
18+
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
19+
import org.testcontainers.azure.ServiceBusEmulatorContainer;
20+
import org.testcontainers.containers.MSSQLServerContainer;
21+
import org.testcontainers.containers.Network;
22+
import org.testcontainers.junit.jupiter.Container;
23+
import org.testcontainers.junit.jupiter.Testcontainers;
24+
import org.testcontainers.utility.MountableFile;
25+
26+
import java.time.Duration;
27+
import java.util.Set;
28+
import java.util.concurrent.ConcurrentHashMap;
29+
30+
import static org.assertj.core.api.Assertions.assertThat;
31+
import static org.awaitility.Awaitility.waitAtMost;
32+
33+
@SpringJUnitConfig
34+
@TestPropertySource(properties = { "spring.cloud.azure.servicebus.entity-name=queue.1",
35+
"spring.cloud.azure.servicebus.entity-type=queue" })
36+
@Testcontainers
37+
class ServiceBusTestContainerTest {
38+
39+
private static final Network NETWORK = Network.newNetwork();
40+
41+
private static final MSSQLServerContainer<?> SQLSERVER = new MSSQLServerContainer<>(
42+
"mcr.microsoft.com/mssql/server:2022-CU14-ubuntu-22.04")
43+
.acceptLicense()
44+
.withNetwork(NETWORK)
45+
.withNetworkAliases("sqlserver");
46+
47+
@Container
48+
@ServiceConnection
49+
private static final ServiceBusEmulatorContainer SERVICE_BUS = new ServiceBusEmulatorContainer(
50+
"mcr.microsoft.com/azure-messaging/servicebus-emulator:latest")
51+
.acceptLicense()
52+
.withCopyFileToContainer(MountableFile.forClasspathResource("Config.json"),
53+
"/ServiceBus_Emulator/ConfigFiles/Config.json")
54+
.withNetwork(NETWORK)
55+
.withMsSqlServerContainer(SQLSERVER);
56+
57+
@Autowired
58+
private AzureServiceBusConnectionDetails connectionDetails;
59+
60+
@Autowired
61+
private ServiceBusSenderClient senderClient;
62+
63+
@Autowired
64+
private ServiceBusTemplate serviceBusTemplate;
65+
66+
@Test
67+
void connectionDetailsShouldBeProvidedByFactory() {
68+
assertThat(connectionDetails).isNotNull();
69+
assertThat(connectionDetails.getConnectionString())
70+
.isNotBlank()
71+
.startsWith("Endpoint=sb://");
72+
}
73+
74+
@Test
75+
void senderClientCanSendMessage() {
76+
// Wait for Service Bus emulator to be fully ready and queue entity to be available
77+
waitAtMost(Duration.ofSeconds(120)).pollInterval(Duration.ofSeconds(2)).untilAsserted(() -> {
78+
this.senderClient.sendMessage(new ServiceBusMessage("Hello World!"));
79+
});
80+
81+
waitAtMost(Duration.ofSeconds(30)).untilAsserted(() -> {
82+
assertThat(Config.MESSAGES).contains("Hello World!");
83+
});
84+
}
85+
86+
@Test
87+
void serviceBusTemplateCanSendMessage() {
88+
// Wait for Service Bus emulator to be fully ready and queue entity to be available
89+
waitAtMost(Duration.ofSeconds(120)).pollInterval(Duration.ofSeconds(2)).untilAsserted(() -> {
90+
this.serviceBusTemplate.sendAsync("queue.1", MessageBuilder.withPayload("Hello from ServiceBusTemplate!").build()).block();
91+
});
92+
93+
waitAtMost(Duration.ofSeconds(30)).untilAsserted(() -> {
94+
assertThat(Config.MESSAGES).contains("Hello from ServiceBusTemplate!");
95+
});
96+
}
97+
98+
99+
@Configuration(proxyBeanMethods = false)
100+
@ImportAutoConfiguration(classes = {AzureGlobalPropertiesAutoConfiguration.class,
101+
AzureServiceBusAutoConfiguration.class,
102+
AzureServiceBusMessagingAutoConfiguration.class})
103+
static class Config {
104+
105+
private static final Set<String> MESSAGES = ConcurrentHashMap.newKeySet();
106+
107+
@Bean
108+
ServiceBusRecordMessageListener processMessage() {
109+
return context -> {
110+
MESSAGES.add(context.getMessage().getBody().toString());
111+
};
112+
}
113+
114+
@Bean
115+
ServiceBusErrorHandler errorHandler() {
116+
// No-op error handler for tests: acknowledge errors without affecting test execution.
117+
return (context) -> {
118+
};
119+
}
120+
121+
}
122+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
{
2+
"UserConfig": {
3+
"Namespaces": [
4+
{
5+
"Name": "sbemulatorns",
6+
"Queues": [
7+
{
8+
"Name": "queue.1",
9+
"Properties": {
10+
"DeadLetteringOnMessageExpiration": false,
11+
"DefaultMessageTimeToLive": "PT1H",
12+
"DuplicateDetectionHistoryTimeWindow": "PT20S",
13+
"ForwardDeadLetteredMessagesTo": "",
14+
"ForwardTo": "",
15+
"LockDuration": "PT1M",
16+
"MaxDeliveryCount": 10,
17+
"RequiresDuplicateDetection": false,
18+
"RequiresSession": false
19+
}
20+
}
21+
],
22+
23+
"Topics": [
24+
{
25+
"Name": "topic.1",
26+
"Properties": {
27+
"DefaultMessageTimeToLive": "PT1H",
28+
"DuplicateDetectionHistoryTimeWindow": "PT20S",
29+
"RequiresDuplicateDetection": false
30+
},
31+
"Subscriptions": [
32+
{
33+
"Name": "subscription.1",
34+
"Properties": {
35+
"DeadLetteringOnMessageExpiration": false,
36+
"DefaultMessageTimeToLive": "PT1H",
37+
"LockDuration": "PT1M",
38+
"MaxDeliveryCount": 10,
39+
"ForwardDeadLetteredMessagesTo": "",
40+
"ForwardTo": "",
41+
"RequiresSession": false
42+
},
43+
"Rules": [
44+
{
45+
"Name": "app-prop-filter-1",
46+
"Properties": {
47+
"FilterType": "Correlation",
48+
"CorrelationFilter": {
49+
"ContentType": "application/text",
50+
"CorrelationId": "id1",
51+
"Label": "subject1",
52+
"MessageId": "msgid1",
53+
"ReplyTo": "someQueue",
54+
"ReplyToSessionId": "sessionId",
55+
"SessionId": "session1",
56+
"To": "xyz"
57+
}
58+
}
59+
}
60+
]
61+
},
62+
{
63+
"Name": "subscription.2",
64+
"Properties": {
65+
"DeadLetteringOnMessageExpiration": false,
66+
"DefaultMessageTimeToLive": "PT1H",
67+
"LockDuration": "PT1M",
68+
"MaxDeliveryCount": 10,
69+
"ForwardDeadLetteredMessagesTo": "",
70+
"ForwardTo": "",
71+
"RequiresSession": false
72+
},
73+
"Rules": [
74+
{
75+
"Name": "user-prop-filter-1",
76+
"Properties": {
77+
"FilterType": "Correlation",
78+
"CorrelationFilter": {
79+
"Properties": {
80+
"prop3": "value3"
81+
}
82+
}
83+
}
84+
}
85+
]
86+
},
87+
{
88+
"Name": "subscription.3",
89+
"Properties": {
90+
"DeadLetteringOnMessageExpiration": false,
91+
"DefaultMessageTimeToLive": "PT1H",
92+
"LockDuration": "PT1M",
93+
"MaxDeliveryCount": 10,
94+
"ForwardDeadLetteredMessagesTo": "",
95+
"ForwardTo": "",
96+
"RequiresSession": false
97+
}
98+
}
99+
]
100+
}
101+
]
102+
}
103+
],
104+
"Logging": {
105+
"Type": "File"
106+
}
107+
}
108+
}

0 commit comments

Comments
 (0)