Skip to content

Commit be412ee

Browse files
authored
add PowerMock integration for easy patching of AWS SDK to use local endpoints (#44)
1 parent 5d9d8b4 commit be412ee

File tree

8 files changed

+499
-11
lines changed

8 files changed

+499
-11
lines changed

README.md

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ extension. Take a look at the example JUnit tests in `src/test/java`.
1919
By default, the JUnit Test Runner starts LocalStack in a Docker container, for the duration of the test.
2020
The container can be configured by using the `@LocalstackDockerProperties` annotation.
2121

22-
```
22+
```java
2323
...
2424
import cloud.localstack.LocalstackTestRunner;
2525
import cloud.localstack.ServiceName;
@@ -42,7 +42,7 @@ public class MyCloudAppTest {
4242

4343
Or with JUnit 5:
4444

45-
```
45+
```java
4646
@ExtendWith(LocalstackDockerExtension.class)
4747
@LocalstackDockerProperties(...)
4848
public class MyCloudAppTest {
@@ -55,7 +55,7 @@ public class MyCloudAppTest {
5555
The LocalStack JUnit test runner is published as an artifact in Maven Central.
5656
Simply add the following dependency to your `pom.xml` file:
5757

58-
```
58+
```xml
5959
<dependency>
6060
<groupId>cloud.localstack</groupId>
6161
<artifactId>localstack-utils</artifactId>
@@ -98,7 +98,8 @@ _Note: When specifying the port in the `services` property, you cannot use `rand
9898
## Building
9999

100100
To build the latest version of the code via Maven:
101-
```
101+
102+
```sh
102103
make build
103104
```
104105

@@ -111,6 +112,55 @@ make build
111112
* v0.2.1: Move Java sources into separate project; mark non-Docker Java `LocalstackExtension` as deprecated; update paths for Python code lookup in Docker container
112113
* v0.2.0: Last version still maintained in LocalStack main repo
113114

115+
## PowerMock
116+
117+
You can use the PowerMock Library to call the builders default method and still get LocalStack version of the AWS clients.
118+
119+
```java
120+
...
121+
@RunWith(PowerMockRunner.class)
122+
@PowerMockRunnerDelegate(LocalstackTestRunner.class)
123+
@LocalstackDockerProperties(services = { "ses" })
124+
@PrepareForTest({ AmazonSimpleEmailServiceClientBuilder.class, AmazonSimpleEmailServiceAsyncClientBuilder.class })
125+
@PowerMockIgnore({"javax.crypto.*", "org.hamcrest.*", "javax.net.ssl.*", "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*", "javax.security.*", "org.w3c.*"})
126+
public class SESMessagingTest {
127+
....
128+
@Before
129+
public void mockSES() {
130+
AmazonSimpleEmailService mockSes = TestUtils.getClientSES();
131+
PowerMockito.mockStatic(AmazonSimpleEmailServiceClientBuilder.class);
132+
when(AmazonSimpleEmailServiceClientBuilder.defaultClient()).thenReturn(mockSes);
133+
}
134+
@Test
135+
public void testSendEmail() throws Exception {
136+
AmazonSimpleEmailService client = amazonSimpleEmailServiceClientBuilder.defaultClient();
137+
....
138+
```
139+
140+
## PowerMockLocalStack Utility
141+
142+
This utility makes easier to use PowerMock with Localstack.
143+
144+
```java
145+
...
146+
public class PowerMockLocalStackExampleTest extends PowerMockLocalStack{
147+
private static final String TOPIC = "topic";
148+
@Before
149+
public void mock() {
150+
PowerMockLocalStack.mockSNS();
151+
}
152+
153+
@Test
154+
public void testSendMessage() throws JMSException {
155+
final AmazonSNS clientSNS = AmazonSNSClientBuilder.defaultClient();
156+
...
157+
}
158+
}
159+
```
160+
161+
## Acknowledgements
162+
I thank you [Keith Humphreys](https://gitlab.com/keithh), for showing us how to empower LocalStack with PowerMock to write tests even easier.
163+
114164
## License
115165

116166
This code is released under the Apache License, Version 2.0 (see LICENSE.txt).

pom.xml

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
33
<modelVersion>4.0.0</modelVersion>
44

55
<groupId>cloud.localstack</groupId>
@@ -75,6 +75,19 @@
7575
<version>1.18.4</version>
7676
<scope>provided</scope>
7777
</dependency>
78+
<dependency>
79+
<groupId>org.powermock</groupId>
80+
<artifactId>powermock-module-junit4</artifactId>
81+
<version>2.0.9</version>
82+
<scope>provided</scope>
83+
</dependency>
84+
<dependency>
85+
<groupId>org.powermock</groupId>
86+
<artifactId>powermock-api-mockito2</artifactId>
87+
<version>2.0.9</version>
88+
<scope>provided</scope>
89+
</dependency>
90+
7891
<!-- required to build on java 9+ -->
7992
<dependency>
8093
<groupId>javax.xml.bind</groupId>
@@ -96,10 +109,10 @@
96109
<version>${aws.sdk.version}</version>
97110
<scope>provided</scope>
98111
<exclusions>
99-
<exclusion>
100-
<groupId>com.amazonaws</groupId>
101-
<artifactId>aws-java-sdk-kinesisvideo</artifactId>
102-
</exclusion>
112+
<exclusion>
113+
<groupId>com.amazonaws</groupId>
114+
<artifactId>aws-java-sdk-kinesisvideo</artifactId>
115+
</exclusion>
103116
</exclusions>
104117
</dependency>
105118
<dependency>
@@ -157,7 +170,7 @@
157170
<version>${aws.sdkv2.version}</version>
158171
<scope>provided</scope>
159172
</dependency>
160-
<dependency>
173+
<dependency>
161174
<groupId>software.amazon.awssdk</groupId>
162175
<artifactId>ssm</artifactId>
163176
<version>${aws.sdkv2.version}</version>
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
package cloud.localstack.awssdkv1;
2+
3+
import org.junit.runner.RunWith;
4+
import org.powermock.api.mockito.PowerMockito;
5+
import org.powermock.core.classloader.annotations.PowerMockIgnore;
6+
import org.powermock.core.classloader.annotations.PrepareForTest;
7+
import org.powermock.modules.junit4.*;
8+
import static org.mockito.Mockito.when;
9+
10+
import com.amazonaws.client.builder.ExecutorFactory;
11+
import com.amazonaws.services.cloudwatch.AmazonCloudWatch;
12+
import com.amazonaws.services.cloudwatch.AmazonCloudWatchClientBuilder;
13+
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
14+
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
15+
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBStreams;
16+
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBStreamsClientBuilder;
17+
import com.amazonaws.services.identitymanagement.AmazonIdentityManagement;
18+
import com.amazonaws.services.identitymanagement.AmazonIdentityManagementAsync;
19+
import com.amazonaws.services.identitymanagement.AmazonIdentityManagementAsyncClientBuilder;
20+
import com.amazonaws.services.identitymanagement.AmazonIdentityManagementClientBuilder;
21+
import com.amazonaws.services.kinesis.AmazonKinesis;
22+
import com.amazonaws.services.kinesis.AmazonKinesisAsync;
23+
import com.amazonaws.services.kinesis.AmazonKinesisAsyncClientBuilder;
24+
import com.amazonaws.services.kinesis.AmazonKinesisClientBuilder;
25+
import com.amazonaws.services.lambda.AWSLambda;
26+
import com.amazonaws.services.lambda.AWSLambdaAsync;
27+
import com.amazonaws.services.lambda.AWSLambdaAsyncClientBuilder;
28+
import com.amazonaws.services.lambda.AWSLambdaClientBuilder;
29+
import com.amazonaws.services.logs.AWSLogs;
30+
import com.amazonaws.services.logs.AWSLogsAsync;
31+
import com.amazonaws.services.logs.AWSLogsAsyncClientBuilder;
32+
import com.amazonaws.services.logs.AWSLogsClientBuilder;
33+
import com.amazonaws.services.s3.AmazonS3;
34+
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
35+
import com.amazonaws.services.simpleemail.AmazonSimpleEmailService;
36+
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceAsync;
37+
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceAsyncClientBuilder;
38+
import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClientBuilder;
39+
import com.amazonaws.services.sns.AmazonSNS;
40+
import com.amazonaws.services.sns.AmazonSNSAsync;
41+
import com.amazonaws.services.sns.AmazonSNSAsyncClientBuilder;
42+
import com.amazonaws.services.sns.AmazonSNSClientBuilder;
43+
import com.amazonaws.services.secretsmanager.AWSSecretsManager;
44+
import com.amazonaws.services.secretsmanager.AWSSecretsManagerClientBuilder;
45+
import com.amazonaws.services.sqs.AmazonSQS;
46+
import com.amazonaws.services.sqs.AmazonSQSAsync;
47+
import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder;
48+
import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
49+
50+
import cloud.localstack.LocalstackTestRunner;
51+
52+
@RunWith(PowerMockRunner.class)
53+
@PowerMockRunnerDelegate(LocalstackTestRunner.class)
54+
@PrepareForTest({ AmazonCloudWatchClientBuilder.class, AmazonDynamoDBClientBuilder.class,
55+
AmazonDynamoDBStreamsClientBuilder.class, AmazonIdentityManagementClientBuilder.class,
56+
AmazonKinesisAsyncClientBuilder.class, AmazonKinesisClientBuilder.class, AWSLambdaAsyncClientBuilder.class,
57+
AWSLambdaClientBuilder.class, AWSLogsClientBuilder.class, AWSLogsAsyncClientBuilder.class,
58+
AmazonS3ClientBuilder.class, AmazonSimpleEmailServiceAsyncClientBuilder.class,
59+
AmazonSimpleEmailServiceClientBuilder.class, AmazonSNSAsyncClientBuilder.class, AmazonSNSClientBuilder.class,
60+
AWSSecretsManagerClientBuilder.class, AmazonSQSClientBuilder.class })
61+
@PowerMockIgnore({ "javax.crypto.*", "org.hamcrest.*", "javax.net.ssl.*", "com.sun.org.apache.xerces.*", "javax.xml.*",
62+
"org.xml.*", "javax.management.*", "javax.security.*", "org.w3c.*" })
63+
public abstract class PowerMockLocalStack {
64+
65+
public static void mockCloudWatch() {
66+
AmazonCloudWatch mockService = TestUtils.getClientCloudWatch();
67+
PowerMockito.mockStatic(AmazonCloudWatchClientBuilder.class);
68+
when(AmazonCloudWatchClientBuilder.defaultClient()).thenReturn(mockService);
69+
}
70+
71+
public static void mockDynamoDB() {
72+
AmazonDynamoDB mockService = TestUtils.getClientDynamoDB();
73+
PowerMockito.mockStatic(AmazonDynamoDBClientBuilder.class);
74+
when(AmazonDynamoDBClientBuilder.defaultClient()).thenReturn(mockService);
75+
}
76+
77+
public static void mockDynamoDBStreams() {
78+
AmazonDynamoDBStreams mockService = TestUtils.getClientDynamoDBStreams();
79+
PowerMockito.mockStatic(AmazonDynamoDBStreamsClientBuilder.class);
80+
when(AmazonDynamoDBStreamsClientBuilder.defaultClient()).thenReturn(mockService);
81+
}
82+
83+
public static void mockIdentityManager() {
84+
AmazonIdentityManagement mockService = TestUtils.getClientIAM();
85+
PowerMockito.mockStatic(AmazonIdentityManagementClientBuilder.class);
86+
when(AmazonIdentityManagementClientBuilder.defaultClient()).thenReturn(mockService);
87+
}
88+
89+
public static void mockIdentityManagerAsync() {
90+
AmazonIdentityManagementAsync mockServiceAsync = TestUtils.getClientIAMAsync();
91+
PowerMockito.mockStatic(AmazonIdentityManagementAsyncClientBuilder.class);
92+
when(AmazonIdentityManagementAsyncClientBuilder.defaultClient()).thenReturn(mockServiceAsync);
93+
}
94+
95+
public static void mockKinesis() {
96+
AmazonKinesis mockService = TestUtils.getClientKinesis();
97+
PowerMockito.mockStatic(AmazonKinesisClientBuilder.class);
98+
when(AmazonKinesisClientBuilder.defaultClient()).thenReturn(mockService);
99+
}
100+
101+
public static void mockKinesisAsync() {
102+
AmazonKinesisAsync mockServiceAsync = TestUtils.getClientKinesisAsync();
103+
PowerMockito.mockStatic(AmazonKinesisAsyncClientBuilder.class);
104+
when(AmazonKinesisAsyncClientBuilder.defaultClient()).thenReturn(mockServiceAsync);
105+
}
106+
107+
public static void mockKinesisAsync(final ExecutorFactory executorFactory) {
108+
AmazonKinesisAsync mockServiceAsync = TestUtils
109+
.getClientKinesisAsync(executorFactory);
110+
PowerMockito.mockStatic(AmazonKinesisAsyncClientBuilder.class);
111+
when(AmazonKinesisAsyncClientBuilder.defaultClient()).thenReturn(mockServiceAsync);
112+
}
113+
114+
public static void mockLambda() {
115+
AWSLambda mockService = TestUtils.getClientLambda();
116+
PowerMockito.mockStatic(AWSLambdaClientBuilder.class);
117+
when(AWSLambdaClientBuilder.defaultClient()).thenReturn(mockService);
118+
}
119+
120+
public static void mockLambdaAsync() {
121+
AWSLambdaAsync mockService = TestUtils.getClientLambdaAsync();
122+
PowerMockito.mockStatic(AWSLambdaAsyncClientBuilder.class);
123+
when(AWSLambdaAsyncClientBuilder.defaultClient()).thenReturn(mockService);
124+
}
125+
126+
public static void mockLambdaAsync(final ExecutorFactory executorFactory) {
127+
AWSLambdaAsync mockService = TestUtils.getClientLambdaAsync(executorFactory);
128+
PowerMockito.mockStatic(AWSLambdaAsyncClientBuilder.class);
129+
when(AWSLambdaAsyncClientBuilder.defaultClient()).thenReturn(mockService);
130+
}
131+
132+
public static void mockLogs() {
133+
AWSLogs mockService = TestUtils.getClientCloudWatchLogs();
134+
PowerMockito.mockStatic(AWSLogsClientBuilder.class);
135+
when(AWSLogsClientBuilder.defaultClient()).thenReturn(mockService);
136+
}
137+
138+
public static void mockLogsAsync() {
139+
AWSLogsAsync mockService = TestUtils.getClientCloudWatchLogsAsync();
140+
PowerMockito.mockStatic(AWSLogsAsyncClientBuilder.class);
141+
when(AWSLogsAsyncClientBuilder.defaultClient()).thenReturn(mockService);
142+
}
143+
144+
public static void mockS3() {
145+
AmazonS3 mockS3 = TestUtils.getClientS3();
146+
PowerMockito.mockStatic(AmazonS3ClientBuilder.class);
147+
when(AmazonS3ClientBuilder.defaultClient()).thenReturn(mockS3);
148+
}
149+
150+
public static void mockSecretsManager() {
151+
AWSSecretsManager mock = TestUtils.getClientSecretsManager();
152+
PowerMockito.mockStatic(AWSSecretsManagerClientBuilder.class);
153+
when(AWSSecretsManagerClientBuilder.defaultClient()).thenReturn(mock);
154+
}
155+
156+
public static void mockSES() {
157+
AmazonSimpleEmailService mockSes = TestUtils.getClientSES();
158+
PowerMockito.mockStatic(AmazonSimpleEmailServiceClientBuilder.class);
159+
when(AmazonSimpleEmailServiceClientBuilder.defaultClient()).thenReturn(mockSes);
160+
}
161+
162+
public static void mockSESAsync() {
163+
AmazonSimpleEmailServiceAsync mockSesAsync = TestUtils.getClientSESAsync();
164+
PowerMockito.mockStatic(AmazonSimpleEmailServiceAsyncClientBuilder.class);
165+
when(AmazonSimpleEmailServiceAsyncClientBuilder.defaultClient()).thenReturn(mockSesAsync);
166+
}
167+
168+
public static void mockSNS() {
169+
AmazonSNS mockService = TestUtils.getClientSNS();
170+
PowerMockito.mockStatic(AmazonSNSClientBuilder.class);
171+
when(AmazonSNSClientBuilder.defaultClient()).thenReturn(mockService);
172+
}
173+
174+
public static void mockSNSAsync() {
175+
AmazonSNSAsync mockService = TestUtils.getClientSNSAsync();
176+
PowerMockito.mockStatic(AmazonSNSAsyncClientBuilder.class);
177+
when(AmazonSNSAsyncClientBuilder.defaultClient()).thenReturn(mockService);
178+
}
179+
180+
public static void mockSNSAsync(final ExecutorFactory executorFactory) {
181+
AmazonSNSAsync mockService = TestUtils.getClientSNSAsync(executorFactory);
182+
PowerMockito.mockStatic(AmazonSNSAsyncClientBuilder.class);
183+
when(AmazonSNSAsyncClientBuilder.defaultClient()).thenReturn(mockService);
184+
}
185+
186+
public static void mockSQS() {
187+
AmazonSQS mockService = TestUtils.getClientSQS();
188+
PowerMockito.mockStatic(AmazonSQSClientBuilder.class);
189+
when(AmazonSQSClientBuilder.defaultClient()).thenReturn(mockService);
190+
}
191+
192+
public static void mockSQS(String endpoint) {
193+
AmazonSQS mockService = TestUtils.getClientSQS(endpoint);
194+
PowerMockito.mockStatic(AmazonSQSClientBuilder.class);
195+
when(AmazonSQSClientBuilder.defaultClient()).thenReturn(mockService);
196+
}
197+
198+
public static void mockSQSAsync() {
199+
AmazonSQSAsync mockService = TestUtils.getClientSQSAsync();
200+
PowerMockito.mockStatic(AmazonSQSAsyncClientBuilder.class);
201+
when(AmazonSQSAsyncClientBuilder.defaultClient()).thenReturn(mockService);
202+
}
203+
204+
public static void mockSQSAsync(final ExecutorFactory executorFactory) {
205+
AmazonSQSAsync mockService = TestUtils.getClientSQSAsync(executorFactory);
206+
PowerMockito.mockStatic(AmazonSQSAsyncClientBuilder.class);
207+
when(AmazonSQSAsyncClientBuilder.defaultClient()).thenReturn(mockService);
208+
}
209+
}

0 commit comments

Comments
 (0)