有没有其他方法可以在构造函数中模拟此方法调用

时间:2019-01-20 07:42:17

标签: java spring mocking mockito

我有这个课: SqssReadderApp

 @Autowired
    private Source source;
    @Autowired
    private AWSProperties awsProperties;
    @Autowired
    private AuditRepository auditRepository;
    private AmazonSQS sqs;

    @Autowired
    public SqssreaderApplication(AWSConfig awsConfig) {
        this.sqs = awsConfig.generateSQS();
    }

它正在从其构造函数中调用方法generateSQS()。 SQS是通过调用静态方法生成的。 这是包含该方法的相关类:

   @Autowired
    private AWSProperties awsProperties;

    @Bean
    AmazonSQS generateSQS() {
        return AmazonSQSClientBuilder.standard()
                .withRegion(awsProperties.getQueueRegion())
                .build();
    }

现在,在我的测试类中,我正在尝试通过注入mockAwsConfig来模拟generateSQS()方法调用。 我认为有两种方法可以将SockSqs实例注入SqssReaderApplication中。

方法1:  我将mockAwsConfig注入构造函数,并使用以下规则对其进行初始化:

when(mockAwsConfig.generateSQS()).thenReturn(mockSQS);
SqssReaderApplication app = new SqssReaderApplication(mockAwsConfig);

问题:     所有重新折叠(@Autowired)实体均保持为空。

方法2:     我@Autowired SqssReaderApplication,所有其他字段都被模拟,但是SqssReaderApplication中的sqs实例保持为空。

**TestClass**:

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@TestPropertySource(locations = "classpath:application-test.properties")
@SpringBootTest
@ContextConfiguration(classes = {SqssreaderApplication.class,
        DefaultFrameworkSupport.class, AWSConfig.class, AuditRepository.class, FileProcessAuditLog.class})
public class SqssreaderApplicationTests {

    @Autowired
    private Source source;

    @MockBean
    AuditRepository auditRepository;
    @Mock
    private AmazonSQSClient amazonSQS;
    @Mock
    private AWSConfig awsConfig;

    @InjectMocks
    private SqssreaderApplication app;
    @Mock
    private AWSProperties awsProperties;

    @Before
    public void setup(){
        MockitoAnnotations.initMocks(this);
        when(awsConfig.generateSQS()).thenReturn(amazonSQS);
        app = new SqssreaderApplication(awsConfig);
    }

我也看到了其他答案,但是在这种情况下它们不起作用。 解决此问题的其他方法是什么?我应该如何在SqssReaderApp中注入模拟,最好不要使用PowerMock或修改源代码?

2 个答案:

答案 0 :(得分:1)

您正在混合两种方式的依赖项注入(https://en.wikipedia.org/wiki/Dependency_injection#Three_types_of_dependency_injection)。您应该创建适当的构造函数,并且只有此委托方应该是@Autowired。 您的课程应类似于:

private Source source;
private AWSProperties awsProperties;
private AuditRepository auditRepository;
private AmazonSQS sqs;

@Autowired
public SqssreaderApplication(Source source, AWSProperties awsProperties, AuditRepository auditRepository, AWSConfig awsConfig) {
    this.sqs = awsConfig.generateSQS();

然后在测试中,您可以修改#1方法并通过构造函数添加所有必需的模拟。 小麻烦:您正在AWSConfig和SqssreaderApplication类中使用AWSProperties。在SqssreaderApplication中检查您是否真的需要它。

答案 1 :(得分:0)

AmazonSQS也是一个可以注入@Autowired的spring bean。因此,您可以从更改

@Autowired
public SqssReadderApp(AWSConfig awsConfig) {
    this.sqs = awsConfig.generateSQS();
}

@Autowired
public SqssReadderApp(AmazonSQS sqs) {
    this.sqs = sqs;
}

现在,您可以将模拟的实例注入到构造函数中。

您还应该考虑解决字段注入和构造函数注入的这种混合问题。我建议使用构造函数注入,这会使测试更加容易。

public class SqssReadderApp {

    @Autowired
    public SqssReadderApp(Source source, AWSProperties awsProperties, AuditRepository auditRepository, AmazonSQS sqs) {
        //
    }
}

另请参阅why field injection is evil