Есть ли другой подход, чтобы смоделировать этот вызов метода в конструкторе - PullRequest
0 голосов
/ 20 января 2019

У меня есть этот класс: 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();
    }

Теперь в моем тестовом классе я пытаюсь смоделировать этот вызов метода generateSQS (), введя mockAwsConfig. Я думаю, что есть два подхода для внедрения экземпляра mockSqs в SqssReaderApplication.

Подход 1: Я вставляю mockAwsConfig в конструктор и инициализирую его следующим правилом:

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

Проблема: Все ремианирующие (@Autowired) сущности остаются нулевыми.

Подход 2: Я @Autowired SqssReaderApplication, все другие поля являются ложными, но экземпляр sqs в SqssReaderApplication остается нулевым.

**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 голосов
/ 20 января 2019

AmazonSQS также является пружинным бобом, который можно вводить с помощью @Autowired.Таким образом, вы можете изменить конструктор с

@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) {
        //
    }
}

См. Также почему инъекция поля - это зло .

0 голосов
/ 20 января 2019

Вы смешиваете два способа внедрения зависимостей (https://en.wikipedia.org/wiki/Dependency_injection#Three_types_of_dependency_injection).. Вы должны создать правильный конструктор, и только этот construstor должен быть @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 и добавить все необходимые макеты через конструктор. Небольшой оффтоп: вы используете AWSProperties как в классах AWSConfig, так и в классах SqssreaderApplication. Проверьте, действительно ли вам это нужно в SqssreaderApplication.

...