为什么在安装之前调用构造方法

时间:2019-01-11 06:45:11

标签: java unit-testing mockito spring-cloud-dataflow

这是我的课程正在测试:

KafkaProcessorApplication

@EnableBinding(Processor.class)
@EnableConfigurationProperties(KafkaProperties.class)
public class KafkaProcessorApplication {

    @Autowired
    private Processor processor;

    @Autowired
    private KafkaProperties kafkaProperties;

    private KafkaTemplate<String, String> kafkaTemplate;

    @Autowired
    KafkaProcessorApplication(SenderConfig senderConfig) {
        this.kafkaTemplate = senderConfig.kafkaTemplate();
    }

在这里,SenderConfig只是一个简单的配置类,使用kafkaTemplate()方法创建了KafkaTemplate的新实例。

SenderConfig

@Configuration
public class SenderConfig {
@Autowired
KafkaProperties kafkaProperties;

public ProducerFactory<String, String> producerFactory() {
    return new DefaultKafkaProducerFactory<>(new HashMap());
}

public KafkaTemplate<String, String> kafkaTemplate() {
    return new KafkaTemplate<>(ProducerFactory()));
}

}

这是测试班:

KafkaTestClass

@SpringBootTest
@ActiveProfiles("test")
@ContextConfiguration(classes = {SenderConfig.class, KafkaProcessorApplication.class})
@TestPropertySource(locations = "classpath:test-resources.properties")
@RunWith(SpringRunner.class)
public class KafkaProcessorApplicationTest {

    @Autowired
    private Processor processor;
    @Mock
    private SenderConfig senderConfig;

    @Mock
    private KafkaProperties kafkaProperties = new KafkaProperties();
    @Mock private KafkaTemplate mockKafka;

    @Autowired
    @InjectMocks
    private KafkaProcessorApplication app;

    @Before
    public void setup() throws Exception {
        MockitoAnnotations.initMocks(this);
        doReturn("ServerConfig").when(kafkaProperties).getServersConfig();
        when(senderConfig.kafkaTemplate()).thenReturn(kafkaTemplate);
    }

我想模拟kafkaTemplate。但是,它的实例化是在构造函数中进行的,该构造函数甚至在执行@Before之前就已执行,在该构造函数中编写了模拟该方法的逻辑。

很好奇为什么首先要执行构造函数,并且在这种情况下我该如何模拟该方法? 在不使用Powermock且不修改被测类的情况下,模拟kafkaTemplate的方法是什么?

1 个答案:

答案 0 :(得分:1)

使用C c = fxn3(fxn1(x1, x2, ...), fxn2(y1, y2, ...));时,在@SpringBootTest方法有机会执行之前,将解析Spring依赖树。这包括构造@Before bean及其依赖项。这就是构造函数在KafkaProcessorApplication之前运行的原因。

您想要的是Spring的@Before在应用程序上下文中创建和注入模拟bean。

这个问题很好地记录了如何使用它:Difference between @Mock, @MockBean and Mockito.mock()

更新

现在我明白了。问题在于@MockBean在配置它之前先在其构造函数中访问该模拟。

这可以通过单独的测试Spring配置来解决,该配置将返回配置的SenderConfig模拟bean,如下所述:Testing spring bean with post construct