Java 如何为本单元测试正确模拟AWS?

Java 如何为本单元测试正确模拟AWS?,java,unit-testing,spring-boot,amazon-s3,amazon-sqs,Java,Unit Testing,Spring Boot,Amazon S3,Amazon Sqs,我想编写一个Spring应用程序,用于侦听SQS消息,然后从S3下载一个文件。我已经完成了所有这些工作,但在为AWS中未涉及的代码区域编写单元测试时遇到了问题。我想模拟所有的AWS进行测试,但我一直遇到这个错误,我还没有找到一种方法来修复它 谢谢你提供的线索 Error creating bean with name 'simpleMessageListenerContainer' defined in class path resource org/springframework/cloud

我想编写一个Spring应用程序,用于侦听SQS消息,然后从S3下载一个文件。我已经完成了所有这些工作,但在为AWS中未涉及的代码区域编写单元测试时遇到了问题。我想模拟所有的AWS进行测试,但我一直遇到这个错误,我还没有找到一种方法来修复它

谢谢你提供的线索

Error creating bean with name 'simpleMessageListenerContainer' 
defined in class path resource org/springframework/cloud/aws/messaging/config/annotation/SqsConfiguration.class
Invocation of init method failed; nested exception is java.lang.NullPointerException
这里是我的简化演示项目,演示了这个问题

测试班

package com.example.demo;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertEquals;

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestConfig.class)
@TestPropertySource(locations= "classpath:application.yml")
public class DemoApplicationTests {

  @MockBean
  DemoApplication demoApplication;

  @Test
  public void nonAwsRelatedTest() {
    int foo = 1;
    assertEquals(1, foo);
  }
}
TestConfig类

package com.example.demo;

import com.amazonaws.services.sqs.AmazonSQSAsync;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.cloud.aws.autoconfigure.context.ContextStackAutoConfiguration;
import org.springframework.cloud.aws.autoconfigure.messaging.MessagingAutoConfiguration;
import org.springframework.cloud.aws.messaging.config.SimpleMessageListenerContainerFactory;
import org.springframework.cloud.aws.messaging.listener.QueueMessageHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import static org.mockito.Mockito.mock;

@TestConfiguration
@EnableAutoConfiguration(exclude = {MessagingAutoConfiguration.class, ContextStackAutoConfiguration.class})
public class TestConfig {

  @MockBean
  AWSConfiguration awsConfiguration;
  @MockBean
  AWS aws;
  @MockBean
  AmazonSQSAsync amazonSQSAsync;

  @Bean
  @Primary
  public SimpleMessageListenerContainerFactory simpleMessageListenerContainerFactory() {
    SimpleMessageListenerContainerFactory factory = new SimpleMessageListenerContainerFactory();
    factory.setAutoStartup(false);
    return factory;
  }

  @Bean(name = "messageHandler")
  public QueueMessageHandler messageHandler() {
    return mock(QueueMessageHandler.class);
  }

  @Bean(name = "amazonSQSAsync")
  public AmazonSQSAsync amazonSQSAsync() {
    return mock(AmazonSQSAsync.class);
  }
}
应用程序类

package com.example.demo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@Slf4j
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  @Override
  public void run(String... args) throws Exception {
    while(true) {
      Thread.sleep(1000);
    }
  }
}
package com.example.demo;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.sqs.AmazonSQSAsync;
import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.aws.messaging.config.annotation.EnableSqs;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
@EnableSqs
public class AWSConfiguration {

  @Value("${aws.region}")
  private String awsRegion;

  @Value("${aws.access-key}")
  private String awsAccessKey;

  @Value("${aws.secret-key}")
  private String awsSecretKey;

  @Bean
  @Primary
  public AmazonSQSAsync amazonSQSAsyncClient() {
    AmazonSQSAsync amazonSQSAsyncClient = AmazonSQSAsyncClientBuilder.standard()
        .withCredentials(amazonAWSCredentials())
        .withRegion(awsRegion)
        .build();
    return amazonSQSAsyncClient;
  }

  @Bean
  public AmazonS3 amazonS3Client() {
    AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
        .withCredentials(amazonAWSCredentials())
        .withRegion(awsRegion).build();
    return s3Client;
  }

  @Bean
  @Primary
  public AWSCredentialsProvider amazonAWSCredentials() {
    return new AWSCredentialsProvider() {
      public void refresh() {}
      public AWSCredentials getCredentials() {
        return new AWSCredentials() {
          public String getAWSSecretKey() {
            return awsSecretKey;
          }
          public String getAWSAccessKeyId() {
            return awsAccessKey;
          }
        };
      }
    };
  }
}
AWS类

package com.example.demo;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.PutObjectResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.aws.messaging.listener.annotation.SqsListener;
import org.springframework.stereotype.Component;
import java.io.File;

@Slf4j
@Component
public class AWS {

  @Autowired
  private AmazonS3 amazonS3;

  @Value("${aws.s3.bucket}")
  private String bucket;

  PutObjectResult upload(String filePath, String uploadKey) {
    File file = new File(filePath);
    return amazonS3.putObject(bucket, uploadKey, file);
  }

  @SqsListener("mysqsqueue")
  public void queueListener(String message) {
    System.out.println("Got an SQS message: " + message);
  }
}
AWS配置类

package com.example.demo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@Slf4j
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {

  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }

  @Override
  public void run(String... args) throws Exception {
    while(true) {
      Thread.sleep(1000);
    }
  }
}
package com.example.demo;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.sqs.AmazonSQSAsync;
import com.amazonaws.services.sqs.AmazonSQSAsyncClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.aws.messaging.config.annotation.EnableSqs;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

@Configuration
@EnableSqs
public class AWSConfiguration {

  @Value("${aws.region}")
  private String awsRegion;

  @Value("${aws.access-key}")
  private String awsAccessKey;

  @Value("${aws.secret-key}")
  private String awsSecretKey;

  @Bean
  @Primary
  public AmazonSQSAsync amazonSQSAsyncClient() {
    AmazonSQSAsync amazonSQSAsyncClient = AmazonSQSAsyncClientBuilder.standard()
        .withCredentials(amazonAWSCredentials())
        .withRegion(awsRegion)
        .build();
    return amazonSQSAsyncClient;
  }

  @Bean
  public AmazonS3 amazonS3Client() {
    AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
        .withCredentials(amazonAWSCredentials())
        .withRegion(awsRegion).build();
    return s3Client;
  }

  @Bean
  @Primary
  public AWSCredentialsProvider amazonAWSCredentials() {
    return new AWSCredentialsProvider() {
      public void refresh() {}
      public AWSCredentials getCredentials() {
        return new AWSCredentials() {
          public String getAWSSecretKey() {
            return awsSecretKey;
          }
          public String getAWSAccessKeyId() {
            return awsAccessKey;
          }
        };
      }
    };
  }
}
application.yml

cloud:
  aws:
    stack:
      auto: false

aws:
  enabled: false
  region: us-east-1
  user: foo
  access-key: ABCDE
  secret-key: 12345

  sqs:
    queue: mysqsqueue

  s3:
    bucket: mybucket

spring:
  autoconfigure:
    exclude:
      - org.springframework.cloud.aws.autoconfigure.context.ContextInstanceDataAutoConfiguration
      - org.springframework.cloud.aws.autoconfigure.context.ContextCredentialsAutoConfiguration
      - org.springframework.cloud.aws.autoconfigure.context.ContextRegionProviderAutoConfiguration
      - org.springframework.cloud.aws.autoconfigure.context.ContextResourceLoaderAutoConfiguration
      - org.springframework.cloud.aws.autoconfigure.context.ContextStackAutoConfiguration
      - org.springframework.cloud.aws.autoconfigure.mail.MailSenderAutoConfiguration
      - org.springframework.cloud.aws.autoconfigure.cache.ElastiCacheAutoConfiguration
      - org.springframework.cloud.aws.autoconfigure.messaging.MessagingAutoConfiguration
      - org.springframework.cloud.aws.autoconfigure.jdbc.AmazonRdsDatabaseAutoConfiguration
      - org.springframework.cloud.aws.autoconfigure.metrics.CloudWatchExportAutoConfiguration
pom相关性

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <version>2.1.6.RELEASE</version>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.1.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.1.6.RELEASE</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-aws</artifactId>
        <version>2.1.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-aws-messaging</artifactId>
        <version>2.1.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.integration</groupId>
        <artifactId>spring-integration-aws</artifactId>
        <version>2.2.0.RELEASE</version>
    </dependency>

org.projectlombok
龙目
真的
org.springframework.boot
spring引导配置处理器
2.1.6.1发布
真的
org.springframework.boot
弹簧靴起动器
2.1.6.1发布
org.springframework.boot
弹簧起动试验
2.1.6.1发布
测试
org.springframework.cloud
春天的云
2.1.2.1发布
org.springframework.cloud
SpringCloudAWS消息传递
2.1.2.1发布
org.springframework.integration
spring集成aws
2.2.0.1发布

答案很简单,我很不好意思问这个问题

只是加上

@MockBean
SimpleMessageListenerContainer simpleMessageListenerContainer;
要测试配置类,请修复它