spring - Groovy Spock:如何在不立即抛出错误的情况下将新异常传递给 when 方法
问题描述
我正在尝试测试一个接受 an 的 kafka 错误处理程序,Exception
但是一旦我在 spock 中声明它,它实际上就会抛出它。
def 'test example'() {
when:
service.emitError(new Exception('test exception'))
then:
// do some tests
}
我尝试在一个包装好的 java 类中声明它并在 main 中运行它不会引发错误,但如果我将它拉入 spock 它将错误地处理它。
我正在尝试查看我是否做错了,或者我是否无法使用 spock 进行测试。
解决方案
在 Jeff 的帮助下,我意识到这是模拟 kafka 模板的错误。当您必须将异常传递给模拟(不确定它是否只是KafkaTemplate
特定的)并且预期的模拟失败时,某些东西会冒泡,而我的 try catch 却抓住了它。我承认我应该发布原始代码 - 并且将来会发布。这是对没有测试(不是 TTD)的预重构代码进行测试
我错过了.key('key')
它失败了。
发射器
public class KafkaErrorNotificationEmitter {
private final KafkaTemplate<String, TopicMessageData> kafkaTemplate;
private final ObjectMapper objectMapper;
private final TemporalConfig.TimeKeeper timeKeeper;
private final String internalErrorTopic;
public KafkaErrorNotificationEmitter(
KafkaTemplate<String, TopicMessageData> kafkaTemplate,
ObjectMapper objectMapper,
TemporalConfig.TimeKeeper timeKeeper,
@Value("${kafka.error.topic}") String internalErrorTopic
) {
this.kafkaTemplate = kafkaTemplate;
this.objectMapper = objectMapper;
this.timeKeeper = timeKeeper;
this.internalErrorTopic = internalErrorTopic;
}
public void emitError(@Nullable KesMessageProperties kesMessageProperties, Exception ex) {
assert kesMessageProperties != null;
String entityName = kesMessageProperties.getEntityName();
log.warn("Failed message ({}). Sending to KES.", entityName, ex);
String key = kesMessageProperties.getMessage().getKey();
try {
TopicMessageData errorMessage =
TopicMessageData
.builder()
.sourceTopic(kesMessageProperties.getTopic())
.exceptionMessage(ex.getMessage())
.key(key)
.listenerType(kesMessageProperties.getListenerType())
.occurrenceTime(timeKeeper.nowZdt())
.payload(objectMapper.writeValueAsString(kesMessageProperties.getMessage()))
.build();
sendEmitError(errorMessage);
} catch (Exception e) {
log.error("Failed to send error ({}) notification for {}", entityName, key, e);
}
}
private void sendEmitError(final TopicMessageData topicMessageData) {
log.debug("Sending error message for: {}", topicMessageData);
kafkaTemplate.send(internalErrorTopic, topicMessageData);
}
}
测试
class KafkaErrorNotificationEmitterSpec extends Specification {
KafkaTemplate<String, TopicMessageData> kafkaTemplate = Mock()
ObjectMapper objectMapper = new ObjectMapper()
TemporalConfig.TimeKeeper timeKeeper = Mock()
String internalErrorTopic = 'kes.error.test'
def kafkaErrorNotificationEmitter = new KafkaErrorNotificationEmitter(
kafkaTemplate,
objectMapper,
timeKeeper,
internalErrorTopic
)
@Shared
def errorMessage = 'Test exception'
@Shared
Exception exception = new Exception(errorMessage)
def 'emitError throws uncaught NPE'() {
setup:
def properties = new KesMessageProperties(message: null)
when:
kafkaErrorNotificationEmitter.emitError(properties, exception)
then:
0 * _
thrown NullPointerException
}
def 'emitError throws caught exception'() {
setup:
def properties = new KesMessageProperties(
message: new IKafkaMessage() {
@Override
String getKey() {
return null
}
}
)
when:
kafkaErrorNotificationEmitter.emitError(properties, exception)
then:
1 * timeKeeper.nowZdt() >> { throw new RuntimeException() }
0 * _
}
def 'emitError success'() {
setup:
def listenerType = 'test-error'
def properties = new KesMessageProperties(
listenerType: listenerType,
message: new IKafkaMessage() {
@Override
String getKey() {
return 'key'
}
}
)
def now = ZonedDateTime.now()
def errorData =
TopicMessageData
.builder()
.exceptionMessage(errorMessage)
.listenerType(listenerType)
//.key('key') // this is what was missing!!!
.occurrenceTime(now)
.payload('{\"key\":\"key\"}')
.build()
when:
kafkaErrorNotificationEmitter.emitError(properties, exception)
then:
1 * timeKeeper.nowZdt() >> now
1 * kafkaTemplate.send(internalErrorTopic, errorData) >> Mock(ListenableFuture)
}
}
推荐阅读
- c++ - STL 或范围算法可有效地找到满足谓词的 n 个连续元素
- python-3.x - 如何使用整数列表在 pd.DataFrame 中查找具有非整数索引的行
- java - lombok AllArgsConstructor 注释中是否包含静态变量?
- python - 计数器功能不适用于我的列表
- python - 使用 pandas 提取组并在图上绘图
- php - 将 SQL 附加到按钮
- blazor - 为什么在 Blazor 的服务器项目中引用客户端项目
- python - 如何使用python仅搜索分隔文本文件的第一列
- wildcard - Express validator-validdate 对象数组作为请求正文
- kubernetes - 从 nexus3 docker 主机拉取 Kubernetes 映像失败