From 719e59dd2b0d21cf8b8d18016a53518b29c876c6 Mon Sep 17 00:00:00 2001 From: Joe McCall Date: Wed, 23 Mar 2022 08:24:05 -0400 Subject: [PATCH 1/2] Task: add test coverage for sendAndReceive for both subscriber types Add unit test to spec the desired behavior when sendAndReceive is called both on a closure subscriber, and on a method subscriber --- .../MethodEventSubscriberSpec.groovy | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/grails-events/src/test/groovy/org/grails/events/subscriber/MethodEventSubscriberSpec.groovy b/grails-events/src/test/groovy/org/grails/events/subscriber/MethodEventSubscriberSpec.groovy index ad739fa8..2a2caed0 100644 --- a/grails-events/src/test/groovy/org/grails/events/subscriber/MethodEventSubscriberSpec.groovy +++ b/grails-events/src/test/groovy/org/grails/events/subscriber/MethodEventSubscriberSpec.groovy @@ -1,13 +1,22 @@ package org.grails.events.subscriber import grails.events.subscriber.MethodSubscriber +import org.grails.events.bus.SynchronousEventBus +import spock.lang.Shared import spock.lang.Specification +import spock.lang.Unroll /** * Created by graemerocher on 28/03/2017. */ class MethodEventSubscriberSpec extends Specification { + @Shared TestHandler testHandler = new TestHandler() + + def setup() { + testHandler.eventHandled = false + } + void "test convert method argument"() { given: TestService testService = new TestService() @@ -18,6 +27,32 @@ class MethodEventSubscriberSpec extends Specification { subscriber.call("1") == 2 subscriber.call("") == null } + + @Unroll + void "sendAndReceive calls reply once subscriber handles the method - #type"() { + + given: + def eventBus = new SynchronousEventBus() + def topic = 'test_topic' + def replied = false + + and: + eventBus.subscribe(topic, subscriber) + + when: + eventBus.sendAndReceive(topic, new Object()) { + replied = true + } + + then: + testHandler.eventHandled + replied + + where: + type | subscriber + 'closure' | { testHandler.handleEvent() } + 'method' | new MethodSubscriber(testHandler, TestHandler.getMethod("handleEvent")) + } } class TestService { @@ -25,3 +60,11 @@ class TestService { return num + 1 } } + +class TestHandler { + boolean eventHandled = false + + def handleEvent() { + eventHandled = true + } +} From f920902a25aaeb027eb96c684ad46adfbe1dc2bb Mon Sep 17 00:00:00 2001 From: Joe McCall Date: Wed, 23 Mar 2022 08:25:27 -0400 Subject: [PATCH 2/2] Ensure reply closure is called on event subscriptions * Follow the same pattern in place for Closure subscriptions * Call the reply closure if it exists on both failure and success cases * Ensure backwards-compatibility by setting the reply closure parameter to null --- .../events/EventSubscriberTrigger.groovy | 22 ++++++++++++++----- .../EventSubscriberSubscription.groovy | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/grails-events/src/main/groovy/org/grails/events/EventSubscriberTrigger.groovy b/grails-events/src/main/groovy/org/grails/events/EventSubscriberTrigger.groovy index 32edc2b8..a919f100 100644 --- a/grails-events/src/main/groovy/org/grails/events/EventSubscriberTrigger.groovy +++ b/grails-events/src/main/groovy/org/grails/events/EventSubscriberTrigger.groovy @@ -18,24 +18,36 @@ import groovy.util.logging.Slf4j class EventSubscriberTrigger implements EventTrigger { final Event event final Subscriber subscriber + final Closure reply - EventSubscriberTrigger(Event event, Subscriber subscriber) { + EventSubscriberTrigger(Event event, Subscriber subscriber, Closure reply = null) { this.event = event this.subscriber = subscriber + this.reply = reply } @Override Object proceed() { try { + def result if(subscriber instanceof EventSubscriber) { - return subscriber.call(event) + result = subscriber.call(event) } else { - return subscriber.call(event.data) + result = subscriber.call(event.data) } + if(reply != null) { + return reply.call(result) + } + return result } catch (Throwable e) { - log.error("Error triggering event [$event.id] for subscriber [${subscriber}]: $e.message", e) - throw e + if(reply != null && reply.parameterTypes && reply.parameterTypes[0].isInstance(e)) { + reply.call(e) + } + else { + log.error("Error triggering event [$event.id] for subscriber [${subscriber}]: $e.message", e) + throw e + } } } } diff --git a/grails-events/src/main/groovy/org/grails/events/registry/EventSubscriberSubscription.groovy b/grails-events/src/main/groovy/org/grails/events/registry/EventSubscriberSubscription.groovy index 3128a379..7667e2c5 100644 --- a/grails-events/src/main/groovy/org/grails/events/registry/EventSubscriberSubscription.groovy +++ b/grails-events/src/main/groovy/org/grails/events/registry/EventSubscriberSubscription.groovy @@ -29,6 +29,6 @@ class EventSubscriberSubscription extends AbstractSubscription { @Override EventTrigger buildTrigger(Event event, Closure reply) { - return new EventSubscriberTrigger(event, subscriber) + return new EventSubscriberTrigger(event, subscriber, reply) } }