In Groovy / Spock I can mock a class by doing:
def theClass = Mock(TheClass.class)
and then wire that instance into the class under unit test. What about if I want to mock a class that has been annotated as a @Singleon
In Groovy / Spock I can mock a class by doing:
def theClass = Mock(TheClass.class)
and then wire that instance into the class under unit test. What about if I want to mock a class that has been annotated as a @Singleon
Here is a little tool class you can use:
package de.scrum_master.stackoverflow
import java.lang.reflect.Field
import java.lang.reflect.Modifier
class GroovySingletonTool<T> {
private Class<T> clazz
GroovySingletonTool(Class<T> clazz) {
this.clazz = clazz
}
void setSingleton(T instance) {
// Make 'instance' field non-final
Field field = clazz.getDeclaredField("instance")
field.modifiers &= ~Modifier.FINAL
// Only works if singleton instance was unset before
field.set(clazz.instance, instance)
}
void unsetSingleton() {
setSingleton(null)
}
void reinitialiseSingleton() {
// Unset singleton instance, otherwise subsequent constructor call will fail
unsetSingleton()
setSingleton(clazz.newInstance())
}
}
Just call setSingleton(Mock(TheClass))
. For more info see this answer, I do not want to repeat the whole sample code here.
Feel free to ask follow-up questions if there is anything you do not understand.
You can use global mocks
def publisher = new Publisher()
publisher << new RealSubscriber() << new RealSubscriber()
def anySubscriber = GroovyMock(RealSubscriber, global: true)
when:
publisher.publish("message")
then:
2 * anySubscriber.receive("message")