I'm trying to figure out if it's possible to disable event listeners in a Spock Unit Test.
I'm working on a service in a Grails app that utilizes event listeners upon saving a new object (an organization). Using a publisher and subscriber here allows me to create a new RecipientGroup and make it the organization's default group in a specific order that seems to work better with Hibernate.
Here's the save method and subscriber to the event from the save method:
class MyService {
@Transactional
@Publisher(Event.ORGANIZATION_CREATED)
Organization save(Organization organization) {
if (Organization.findByName(organization.name))
throw new Exception('organization.create.exists')
organization.save(failOnError: true)
sendSignupNotification(organization)
metricsService.createDefaults(organization)
return organization
}
@Transactional
@Subscriber(Event.ORGANIZATION_CREATED)
void createDefaultRecipientGroup(Organization org) {
Organization organization = organizationDataService.get(org.id)
organization.defaultGroup = new RecipientGroup(organization: organization).save(failOnError: true, flush: true)
organization.save(flush: true)
}
}
However, this breaks some of my unit tests, cannot invoke method get() on a null object
in reference to organizationDataService.get() in my subscriber method. I would prefer to split up the creation of the object and these extra tasks into different unit tests. So, I'm trying to figure out if there is a way to disable the publisher or listener during my test. Also open to other ideas on how to structure this.
Here's the test:
void "test that the organization save method correctly sets up default Recipient group"() {
setup:
String foo = "foo"
when:
Organization organization = new Organization(name: foo)
service.save(organization)
and: "the default recipient group is created"
RecipientGroup.findByOrganization(organization)
and:
1 * mockTextService.send(_, true)
and:
0 * _
}
Thanks in advance!
Revisiting this because I have a viable workaround to this now. Unit tests appear to only pick up publisher/subscriber annotations in the class being tested. Moving the subscriber into a different service is allowing the desired behavior of disabling the event listener for testing, so I can then build out separate unit tests for the two methods in question:
class MyService1 {
@Transactional
@Publisher(Event.ORGANIZATION_CREATED)
Organization save(Organization organization) {
if (Organization.findByName(organization.name)) throw new Exception('organization.create.exists')
organization.save(failOnError: true)
sendSignupNotification(organization)
metricsService.createDefaults(organization)
return organization
}
}
class MyService2 {
@Transactional
@Subscriber(Event.ORGANIZATION_CREATED)
void createDefaultRecipientGroup(Organization org) {
Organization organization = organizationDataService.get(org.id)
organization.defaultGroup = new RecipientGroup(organization: organization).save(failOnError: true, flush: true)
organization.save(flush: true)
}
}