在我的Java
类中有以下方法:
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);
}
我希望能够模拟sqs.sendMessage(sendMessageRequest);
的行为,这样我的单元测试就不会向队列发送消息。
我在我的测试类中尝试这样做,但是在执行测试时,sqs
实际上向队列发送了一条消息。假设这是由AmazonSQSClientBuilder.defaultClient()
分配的。
我怎么才能解决这个问题?
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("");
}
}
发布于 2021-01-31 01:11:15
我建议使用文章中的方法:https://github.com/mockito/mockito/wiki/Mocking-Object-Creation
您需要修改一些类,以下列方式应用文章中的嘲讽方法:
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("");
}
}
发布于 2021-01-29 15:19:32
下面是一个使用模拟测试SQS (sendMessage)的示例。它传递并没有向队列发送实际消息。当您使用模拟时,您不是在调用真正的AWS端点。它只是测试API,而不是修改AWS资源。
SQS模拟码
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");
}
}
发布于 2021-02-04 23:09:55
Mocking static methods with Mockito是可能的,使用PowerMock
。
下列测试工作:
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClientBuilder;
import com.amazonaws.services.sqs.model.SendMessageRequest;
import com.amazonaws.services.sqs.model.SendMessageResult;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.mockito.ArgumentMatchers.any;
@RunWith(PowerMockRunner.class)
@PrepareForTest(AmazonSQSClientBuilder.class)
public class AwsSQSReferralsUtilTest {
private AwsHelper awsHelper = new AwsHelper();
@Mock
AmazonSQS sqs;
@BeforeClass
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@AfterMethod
public void afterEachMethod() {
Mockito.reset(awsHelper);
}
@Test
public void shouldSendMessage() {
PowerMockito.mockStatic(AmazonSQSClientBuilder.class);
BDDMockito.given(AmazonSQSClientBuilder.defaultClient()).willReturn(sqs);
Mockito.when((sqs.sendMessage(any(SendMessageRequest.class)))).thenReturn(new SendMessageResult());
awsHelper.sendMessageToQueue("");
}
}
不改变你的任何源代码。我不确定您是否可以使用它,因为这个解决方案使用junit
,而您用testng
标记这个问题。
在尝试使用testng
运行时,我遇到了以下问题:
powermock not prepared for test
所以我用post Mockito asks to add @PrepareForTest for the class even after adding @PrepareForTest解决了这个问题。
https://stackoverflow.com/questions/65956878
复制相似问题