【发布时间】:2020-09-30 10:23:13
【问题描述】:
我知道这个问题的答案是:您不测试私有方法,而只测试最终会导致该私有方法调用的公共方法。
但是 在我的例子中,公共方法实际上启动了一个消费者/连接到 kafka,所以我只想测试收到 kafka 消息时完成的逻辑。 我不想公开逻辑方法,因为没有人会在 kafka 基础架构之外使用它,但我仍然想对那里完成的逻辑进行单元测试。
最佳实践解决方案是什么?如果需要,我可以更改代码
这里有一些例子:
有问题的私有方法
private void handleConsumerRecord(ConsumerRecord<PK, byte[]> cr, Acknowledgment acknowledgment) throws IOException {
//logic to be tested
}
调用私有逻辑方法的私有方法
/**
* Initialize the kafka message listener
*/
private void initConsumerMessageListenerContainer(ProducerFactory<PK, V> producerFactory) {
if (!processAsBatch) {
// start a acknowledge message listener to allow the manual commit
acknowledgingMessageListener = (cr, acknowledgment) -> {
try {
handleConsumerRecord(cr, acknowledgment);
} catch (IOException e) {
log.error("Failed to handle consumed message, commiting message and performing irrecoverableException actions");
exceptionHandlerManager.getIrrecoverableExceptionHandler().performAction(null, cr.value(), cr.topic(), cr.key());
}
};
// start and initialize the consumer container
container = initContainer(acknowledgingMessageListener, producerFactory);
}
这是启动一切的公共方法
/**
* Start the message consumer
* The record event will be delegate on the onMessage()
*/
public void start(ProducerFactory<PK, V> producerFactory) {
initConsumerMessageListenerContainer(producerFactory);
container.start();
}
我尝试编写的单元测试
kafkaByteArrConsumer.getAcknowledgingMessageListener().onMessage(record, acknowledgment);
doThrow(TemporaryException.class).when(kafkaByteArrConsumer).getConsumerMessageLogic().onMessage(record.value(), acknowledgment);
Mockito.verify(exceptionHandlerManager.getTemporaryExceptionHandler(), Mockito.times(1))
.performAction();
如您所见,getAcknowledgingMessageListener 不会被initConsumerMessageListenerContainer() 初始化,因此在模拟.getConsumerMessageLogic().onMessage 时我将无法访问handleConsumer 方法
(由//一些待测逻辑部分调用)
【问题讨论】:
-
我认为一些单元测试框架可以测试私有方法。反射和宽容的安全管理器将允许这样做。 OTOH 我经常制作一个私有方法包私有,以便可以使用测试工具直接调用它(它本身在同一个包中)。我添加了一条注释,在这些情况下,方法是包私有的“仅用于测试”。
-
是的,我知道 PowerMock 可以测试私有方法...但我想要最佳实践解决方案,我似乎无法考虑可以解决它的设计更改,我确定有一个。