【问题标题】:How to correctly stop and start a localstack instance如何正确停止和启动 localstack 实例
【发布时间】:2022-07-03 17:12:05
【问题描述】:

我正在使用 Localstack 编写集成测试。我想测试的场景之一是 AWS 服务抛出错误。我的测试看起来像


    void saveEventsAsync_snsError() throws Exception{

       
        localSns.stop();

        mvc.perform( MockMvcRequestBuilders
                        .post("/events-async")
                        .content(validRequest())
                        .contentType(MediaType.APPLICATION_JSON)
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isInternalServerError());


    }

但是,这样做会因HttpConnection refused.. 错误而导致另一项测试失败。大概在测试运行时容器没有启动。 我在这里有什么选择?循环使用localSns.isRunning() 似乎没有帮助

这是完整的测试类供参考

package ....

import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.http.MediaType;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.containers.wait.strategy.DockerHealthcheckWaitStrategy;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.model.CreateTopicRequest;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.testcontainers.containers.localstack.LocalStackContainer.Service.SNS;

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("test")
@Testcontainers
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class EventReportingControllerTest {

    @Autowired
    MockMvc mvc;

    @Container
    private static final LocalStackContainer localSns =
            new LocalStackContainer(DockerImageName.parse("localstack/localstack:0.11.3"))
                    .withServices(SNS);

    private static SnsClient snsClient;

    private static String topicArn ;

    @BeforeAll
    static void beforeAll() {
        localSns.start();

        snsClient = SnsClient.builder()
                .endpointOverride(localSns.getEndpointOverride(SNS))
                .credentialsProvider(
                        StaticCredentialsProvider.create(
                                AwsBasicCredentials.create(localSns.getAccessKey(), localSns.getSecretKey())
                        )
                )
                .region(Region.of(localSns.getRegion()))
                .build();

        topicArn = snsClient.createTopic(CreateTopicRequest.builder().name("testTopic").build()).topicArn();
    }

    @DynamicPropertySource
    public static void overrideProps(DynamicPropertyRegistry registry){
        registry.add("events.sns.topic.arn", () -> snsClient.createTopic(CreateTopicRequest.builder().name("testTopic").build()).topicArn());
    }

    @TestConfiguration
    public static class SnsClientConfig {
        @Bean
        @Profile("test")
        public SnsClient amazonSNSClient() {
            return snsClient;
        }
    }

    @Test
    void saveEventsAsync_success() throws Exception{
        mvc.perform( MockMvcRequestBuilders
                        .post("/events-async")
                        .content(validRequest())
                        .contentType(MediaType.APPLICATION_JSON)
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isAccepted()
                );
    }

    @Test
  
    void saveEventsAsync_invalidRequest() throws Exception{
        mvc.perform( MockMvcRequestBuilders
                        .post("/events-async")
                        .content(invalidRequest())
                        .contentType(MediaType.APPLICATION_JSON)
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isBadRequest());
    }

    @Test
    void saveEventsAsync_snsError() throws Exception{

    
        localSns.stop();
        mvc.perform( MockMvcRequestBuilders
                        .post("/events-async")
                        .content(validRequest())
                        .contentType(MediaType.APPLICATION_JSON)
                        .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isInternalServerError());


    }

   
}

【问题讨论】:

标签: testcontainers localstack junit-jupiter


【解决方案1】:

当您使用@Testconainers@Container 进行设置时,Testcontainers 将为您管理容器的生命周期。

因此,您目前混合了自我管理和“由 Testcontainers 管理”。

如果您想接管生命周期处理,请删除两个注释并根据您的喜好启动/停止容器。

PS:如果您使用的是最新的 Spring Cloud AWS 版本,overriding the AWS SDK client is way simpler now

【讨论】:

    猜你喜欢
    • 2022-01-21
    • 2022-11-18
    • 2018-08-15
    • 2019-08-03
    • 2022-12-13
    • 1970-01-01
    • 2019-12-08
    • 2022-10-13
    • 2020-09-25
    相关资源
    最近更新 更多