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+ }
0 commit comments