首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在单元测试中模拟AmazonSQS而不调用SQS?

如何在单元测试中模拟AmazonSQS而不调用SQS?
EN

Stack Overflow用户
提问于 2021-01-29 15:02:01
回答 3查看 15.6K关注 0票数 8

在我的Java类中有以下方法:

代码语言:javascript
运行
复制
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()分配的。

我怎么才能解决这个问题?

代码语言:javascript
运行
复制
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("");
        }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-01-31 01:11:15

我建议使用文章中的方法:https://github.com/mockito/mockito/wiki/Mocking-Object-Creation

您需要修改一些类,以下列方式应用文章中的嘲讽方法:

AwsHelper

代码语言:javascript
运行
复制
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

代码语言:javascript
运行
复制
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("");
    }

}
票数 5
EN

Stack Overflow用户

发布于 2021-01-29 15:19:32

下面是一个使用模拟测试SQS (sendMessage)的示例。它传递并没有向队列发送实际消息。当您使用模拟时,您不是在调用真正的AWS端点。它只是测试API,而不是修改AWS资源。

SQS模拟码

代码语言:javascript
运行
复制
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");
    }
}
票数 1
EN

Stack Overflow用户

发布于 2021-02-04 23:09:55

Mocking static methods with Mockito是可能的,使用PowerMock

下列测试工作:

代码语言:javascript
运行
复制
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运行时,我遇到了以下问题:

代码语言:javascript
运行
复制
powermock not prepared for test

所以我用post Mockito asks to add @PrepareForTest for the class even after adding @PrepareForTest解决了这个问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65956878

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档