简体   繁体   English

Groovy Spock:如何在不立即抛出错误的情况下将新异常传入 when 方法

[英]Groovy Spock: How do you pass in new Exception into when method without throwing error right away

I am trying to test a kafka error handler that takes in an Exception but as soon as I declare it in spock it actually throws it.我正在尝试测试一个接受Exception的 kafka 错误处理程序,但是一旦我在 spock 中声明它,它实际上就会抛出它。

def 'test example'() {
    when:
    service.emitError(new Exception('test exception'))

    then:
    // do some tests
}

I have tried declaring it in a wrapped java class and running that in main will NOT throw an error but if I pull it into spock it will process it incorrectly.我试过在一个包装的 java 类中声明它并在 main 中运行它不会抛出错误,但如果我将它拉入 spock 它将错误地处理它。

I am trying to see if I am doing it wrong or if I can't test this with spock.我想看看是我做错了还是我不能用 spock 测试这个。

With help from Jeff I realized that it was an error on mock kafka template.在 Jeff 的帮助下,我意识到这是模拟 kafka 模板的错误。 When you have to pass an exception into a mock (not sure if it is just KafkaTemplate specific) and the expected mock fails something bubbles up and my try catch caught that instead.当您必须将异常传递到模拟中(不确定它是否只是KafkaTemplate特定的)并且预期的模拟失败时,某些东西冒泡了,而我的 try catch 却抓住了它。 I recognize I should have posted the original code - and will in the future.我知道我应该发布原始代码 - 并且将来会发布。 This is testing on pre-refactored code that didn't have tests (not TTD)这是对没有测试的预重构代码(不是 TTD)的测试

I was missing .key('key') which was failing it.我错过了失败的.key('key')

Emitter发射器

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);
    }

}

Test测试

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)
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Groovy Spock - 模拟方法未返回所需值 - Groovy Spock - mocked method not returning desired value Spock框架在模拟@component时抛出错误 - Spock framework throwing error while mocking a @component Spring rabbitmq 如何在错误处理程序上手动确认,在抛出特定所需的异常时,只有在确认设置为 AUTO 时才会确认 - Spring rabbitmq how to do manually ack on Error handler , On throwing specific required exception, it only ack when Acknowledge is set to AUTO 如何对必须传递 class 具有可访问性 scope 的 bean 的服务进行单元测试? [史波克] - How to unit test service where you have to pass bean that class is of accessibility scope? [Spock] 在grails应用程序中多次触发Datasource.groovy(第二次调用时引发异常) - multiple times triggering of Datasource.groovy in grails application ( throwing exception when called second time) Groovy Spock如何接线或模拟弹簧自动接线接口 - Groovy Spock How to Wire or Mock Spring Autowired Interface 如何在 Spock groovy 中模拟 RequestEntity.put() 和 restTemplate.exchange() - How to mock RequestEntity.put() and restTemplate.exchange() in Spock groovy 如何使这个 spring class 找不到错误 go 消失? - How do I make this spring class not found error go away? Aspectj(带 spring)- 在没有传播方法的情况下,仅在抛出方法上记录异常抛出一次 - Aspectj (with spring) - logging throw of an exception only once on the throwing method without the propagated methods 将来引发异常时如何回滚事务? - How can I rollback transaction when throwing an exception in future?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM