I have the following method in my Java
class:
public class AwsHelper {
private AmazonSQS sqs;
private void sendMessageToQueue(String message){
sqs = AmazonSQSClientBuilder.defaultClient();
SendMessageRequest sendMessageRequest = new SendMessageRequest();
sendMessageRequest.setQueueUrl("");
sendMessageRequest.setMessageBody(message);
sendMessageRequest.setMessageGroupId("");
sqs.sendMessage(sendMessageRequest);
}
I want to be able to mock the behavior of sqs.sendMessage(sendMessageRequest);
so that my unit test does not send a message to a queue.
I have tried to do so as follows in my test class, but sqs
actually sends a message to the queue when my test is executed. Assume this is due to being assigned by AmazonSQSClientBuilder.defaultClient()
.
How can I solve this?
public class AwsSQSReferralsUtilTest {
@Spy
@InjectMocks
private AwsHelper awsHelper;
@Mock
AmazonSQS sqs;
@BeforeClass
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@AfterMethod
public void afterEachMethod() {
Mockito.reset(awsHelper);
}
@Test
public void shouldSendMessage() {
Mockito.when((sqs.sendMessage(any(SendMessageRequest.class)))).thenReturn(new SendMessageResult());
awsHelper.sendMessageToQueue("");
}
}
While doing unit testing using junit you will come across places where you want to mock classes. Mocking is done when you invoke methods of a class that has external communication like database calls or rest calls.
In SQS, one of the attributes for a message that appears in SQS console in the Receive Count which is a numeric property. After a message is created, the receive count property increases even though no interaction has happened or the same message has not been resent.
I recommend to use approach from article: https://github.com/mockito/mockito/wiki/Mocking-Object-Creation
You need to change little bit a class, applying approach for mocking from article in following way:
AwsHelper
public class AwsHelper {
private AmazonSQS sqs;
public void sendMessageToQueue(String message) {
sqs = defaultClient();
SendMessageRequest sendMessageRequest = new SendMessageRequest();
sendMessageRequest.setQueueUrl("");
sendMessageRequest.setMessageBody(message);
sendMessageRequest.setMessageGroupId("");
sqs.sendMessage(sendMessageRequest);
}
protected AmazonSQS defaultClient() {
return AmazonSQSClientBuilder.defaultClient();
}
}
AwsSQSReferralsUtilTest
public class AwsSQSReferralsUtilTest {
@Spy
private AwsHelper awsHelper;
@Mock
private AmazonSQS sqs;
@BeforeClass
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@AfterMethod
public void afterEachMethod() {
Mockito.reset(awsHelper);
}
@Test
public void shouldSendMessage() {
//mocking object creation
doReturn(sqs).when(awsHelper).defaultClient();
when(sqs.sendMessage(any(SendMessageRequest.class))).thenReturn(new SendMessageRequest());
awsHelper.sendMessageToQueue("");
}
}
Here is an example of using MOCK to test SQS API (sendMessage). It passed and did not send the queue an actual message. When you use MOCK, you are not invoking real AWS endpoints. Its just testing the API - not modifying AWS resources.
Code for SQS Mock
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.*;
import java.io.*;
import java.util.*;
import static org.mockito.Mockito.mock;
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class SQSServiceMock {
private static SqsClient sqsClient;
private static String queueName ="";
private static String queueUrl ="" ; // set dynamically in the test
private static String message ="";
private static String dlqueueName ="";
private static List<Message> messages = null; // set dynamically in the test
@BeforeAll
public static void setUp() throws IOException {
try {
sqsClient = mock(SqsClient.class);
} catch (Exception ex) {
ex.printStackTrace();
}
try (InputStream input = SQSServiceIntegrationTest.class.getClassLoader().getResourceAsStream("config.properties")) {
Properties prop = new Properties();
if (input == null) {
System.out.println("Sorry, unable to find config.properties");
return;
}
//load a properties file from class path, inside static method
prop.load(input);
// Populate the data members required for all tests
queueName = prop.getProperty("QueueName");
message = prop.getProperty("Message");
dlqueueName=prop.getProperty("DLQueueName");
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Test
@Order(1)
public void whenInitializingAWSS3Service_thenNotNull() {
assertNotNull(sqsClient);
System.out.println("Test 1 passed");
}
@Test
@Order(2)
public void SendMessage() {
SendMessageRequest sendMsgRequest = SendMessageRequest.builder()
.queueUrl("https://sqs.us-east-1.amazonaws.com/000000047983/VideoQueue")
.messageBody(message)
.delaySeconds(5)
.build();
sqsClient.sendMessage(sendMsgRequest);
System.out.println("Test 2 passed");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With