Grails integration test mock not cleaned - grails

I've a strange polluting situation between two spock integration tests that I'm not able to resolve. I suppose that I'm doing something wrong but I can't understand what.
The two integration tests are testing different situation of the same controller. In the first one I mock a service while in the second I don't mock.
Here are the significant parts of two tests :
test 1:
// CodeControllerSpec.groovy
...
def controller = new CodeController()
def serviceMock = new MockFor(PollutingService)
serviceMock.demand.search(1) { a, b, c ->
return [id: 1]
}
controller.myService.pollutingService = serviceMock.proxyInstance()
controller.save()
...
then:
serviceMock.verify(controller.myService.pollutingService)
test 2:
// CodeEngineSpec.groovy
...
def controller = new CodeController()
controller.show()
...
then:
...
Controller and services are as following
// CodeController
class CodeController extends RestfulController<Code> {
def myService
def show() {
...
myService.execute()
...
}
}
// MyService
class MyService {
def pollutingService
def execute() {
...
pollutingService.search(a, b, c)
...
}
}
// PollutingService
class PollutingService {
def search(a, b, c) {
...
...
}
}
If I run the two tests one by one, they all pass but, if I run them together, the second one fails with
No more calls to 'search' expected at this point. End of demands.
I'm sure that the mock in the first service is used (I've debugged code line by line) but I don't know why mock is not cleaned after test.
Any suggestion is really welcome.
I'm using grails 2.3.8

First of all, using mocks in integration tests has unpredictable results.
But putting that aside, where is controller.myService in your first test being instantiated? I would have expected that calling controller = new CodeController() would bypass autowiring of controller.myService.

Related

How do you make a feature method conditional

In my Test, I have some feature methods that only need to run in certain situations. My code looks something like this:
class MyTest extends GebReportingSpec{
def "Feature method 1"(){
when:
blah()
then:
doSomeStuff()
}
def "Feature method 2"(){
if(someCondition){
when:
blah()
then:
doSomeMoreStuff()
}
}
def "Feature method 3"(){
when:
blah()
then:
doTheFinalStuff()
}
}
I should note I am using a custom spock extension that allows me to run all feature methods of a spec even if a previous feature method fails.
The thing I just realized and the reason I am making this post, is because "Feature method 2" does not show up in my test results for some reason, but method 1 and 3 do. Even if someCondition is set to true, it does not appear in the build results. so I am wondering why this is, and how I can make this feature method conditional
Spock has special support for conditionally executing features, take a look at #IgnoreIf and #Requires.
#IgnoreIf({ os.windows })
def "I'll run everywhere but on Windows"() { ... }
You can also use static methods in the condition closure, they need to use the qualified version.
class MyTest extends GebReportingSpec {
#Requires({ MyTest.myCondition() })
def "I'll only run if myCondition() returns true"() { ... }
static boolean myCondition() { true }
}
Your test is not appearing in the report as you cant have the given, when, then blocks inside of a conditional.
You should always run the test but allow the test to fail gracefully:
Use the #FailsWith attribute. http://spockframework.org/spock/javadoc/1.0/spock/lang/FailsWith.html
#FailsWith(value = SpockAssertionError, reason = "Feature is not enabled")
def "Feature method 2"(){
when:
blah()
then:
doSomeMoreStuff()
}
Important to note that this test will be reported as passed when it fails with the specified exception. And it will also reported as passed if the feature is enabled and the test actually passed.
To Fix this I simply put a when/then block with a 10 ms sleep before the if statement and now that feature method is being executed

Grails, Integration Testing, mocking a bean method while testing a service with Spock

I'm having an issue performing an integration test in Grails 2.4.5.
The service I want to test looks like this:
class MyService {
def myBean
def serviceMethod() {
myBean.beanMethod()
}
}
where myBean is defined in resources.groovy:
beans = {
myBean(MyBeanImpl)
}
And here comes the integration test:
MyServiceIntegrationSpec extends IntegrationSpec {
def myService
def setup() {
def myBeanMock = Mock(MyBeanImpl)
myBeanMock.beanMethod(_) >> 'foo'
myService.myBean = myBeanMock
}
void "silly test"() {
expect:
myService.serviceMethod() == 'foo'
}
}
Well, this badly fails since myService.serviceMethod() returns null.
I've already tried
ReflectionTestUtils.setField(myService, 'myBean', myBeanMock)
instead of
myService.myBean = myBeanMock
with no luck.
Of course this simplified example could be handled with a unit test, but the real case I'm facing needs an integration test since data persistence is involved.
myBeanMock.beanMethod(_) >> 'foo' expects one parameter.
You can either use
myBeanMock.beanMethod() >> 'foo'
or
myBeanMock.beanMethod(*_) >> 'foo'.
Either case mocking should not be part of Integration spec because this is an integration test. In your case as explained, there might be a need.

Grails spock service test not calling service method

I'm seeing some strange behavior in a spock test for a service using Grails 2.3.7.
This test works fine:
void "create spot order"() {
given:
def createOrderCommand = newCreateOrderCommand(OrderType.S)
when:
def orderId = service.createOrder(createOrderCommand, user).id.toInteger()
then:
Order.count() == 1
when:
def order = service.orderById(orderId)
then:
// a bunch of assertions
}
This test also works fine:
void "create command with invalid order id"() {
when:
service.commandForOrderId(999)
then:
def exception = thrown(CreateOrderException)
exception.key == "orderService.invalid.order.id"
}
However this test fails - I've set a breakpoint at the beginning commandForOrderId, and it is never hit. command is null (this is where the test fails, on the line checking for null on command), which would never be returned from this service method:
void "create spot command"() {
given:
def createOrderCommand = newCreateOrderCommand(OrderType.S)
when:
def order = service.createOrder(createOrderCommand, user)
then:
Order.count() == 1
when:
def orderId = order.id.toInteger()
def command = service.commandForOrderId(orderId)
then:
command
// a bunch more assertions
}
I've tried removing the #Transactional annotation from the service, using the transactional static field, as well as using neither of these. I've also tried changing the service method to a closure, all with no luck.
I changed the service method to a closure, cleared my target directories, did every manner of clean I know of (within GGTS and grails commands), and the service method started getting hit in the test. I'm still unsure of the actual cause of this error, however.

What is wrong with my Spec?

So, I have this pretty simple Spec below. I have a class that is not a controller or service or anything like that. It's a Job class. It depends on two services: updateService and directoryTypeService. It runs a Redis async job and it's under /grails-app/jobs folder.
All I want is to make sure that whenever I invoke this job#perform() method (which return type is void), a given dependent method called UpdateService#completeClaiming is invoked, but UpdateService#requestNewPin is not. (Listing is a domain class, by the way).
When I run this Spec, I keep getting an error message saying: "No more calls to 'completeClaiming' expected at this point. End of demands."
What am I doing wrong here? Any wild guesses?
#Mock(Listing)
class SubmissionJobSpec extends Specification {
def directoryTypeServiceMock
def updateServiceMock
def job
def setup(){
job = new SubmissionJob()
directoryTypeServiceMock = mockFor(DirectoryTypeService)
updateServiceMock = mockFor(UpdateService)
job.updateService = updateServiceMock.createMock()
job.directoryTypeService = directoryTypeServiceMock.createMock()
}
def "if the directory is enabled and the pin status is ENTERED, we should call updateService.completeClaiming"() {
given:
directoryTypeServiceMock.demand.isUpdateEnabled { DirectoryType d, Country c -> return true}
new Listing(
location: new Location(country: Country.DE)
).save(failOnError: true, validate: false)
when:
job.perform(Listing.last().id, true)
then:
1 * updateServiceMock.completeClaiming(Listing.last(), true) >> new ListingEvent(output: [success: true])
0 * updateServiceMock.requestNewPin(_ as Listing, true)
}
You seem to be confusing Groovy and Spock mocks. You can't use Spock mocking syntax (e.g. 0 * updateServiceMock.requestNewPin(_ as Listing, true)) for a Groovy mock created with mockFor(). Spock mocks are created using Mock(), Stub() or Spy(). I'm not aware of any good reason to use a Groovy mock in a Spock spec.

Grails Quartz Job Integration test - Not autowired Job

I'm writing the Integration test for a Quartz Job in a grails application.
I've the Job in grails-app/jobs folder, and if I start the application it works. The problem is that I want to get it in an integration test, but the autowire won't work. The test is like:
class MyJobTest{
MyJob myJob
def setUp(){
assert myJob != null
}
def testExecute(){
//test logic
}
}
but it fails because myJob is null...some help?
Quartz Jobs are not autowired like services are under the test environment. The documentation for the Quartz job also explicitly states that by default it will not execute on schedule under the test environment (you could change that if you want to but I wouldn't). I would just instantiate myJob = new MyJob() in your setUp and call the execute() method to test it. If you're trying to test the triggers you may want to find a way to look at what is inside the triggers {} maybe inspecting the metaClass?
EDIT IN RESPONSE TO COMMENT:
I've never gotten the services out of the application context so that might work. The way I would probably test it is as follows:
Assuming your class looks something like this:
class MyJob {
def myServiceA
def myServiceB
def execute() {
if(myJobLogicToDetermineWhatToDo) {
myServiceA.doStuff(parameter)
} else {
myServiceB.doStuff(parameter)
}
}
}
What you're really wanting to test here is the myJobLogicToDetermineWhatToDo. I would assume that you have (or can easily write) integration and/or unit tests against your services myServiceA and myServiceB to ensure that they are working correctly. I would then write unit tests to test the logic/wiring of your Job to the appropriate service.
#Test
void routeOne() {
def job = new MyJob()
def myServiceA = new Object()
def expectedParameter = "Name"
def wasCalled = false
myServiceA.metaClass.doStuff = {someParameter ->
assert expectedParameter == someParameter
wasCalled = true
}
job.myServiceA = myServiceA
//Setup data to cause myServiceA to be invoked
job.execute()
assert wasCalled
}
Then repeat this process for all of the routes you have through your Job. This way you can isolate your tests down to the smallest part possible and test the logic of the object that you're invoking not the services it is using. I would assume you're using a service because the logic in there is being used by another part of the system. If you're testing the service through this job and for some reason the job goes away then you have to re-write your tests to invoke the service directly. The way that I've proposed you have tests testing the service directly and tests that mock out those service calls. If the job goes away you would simply delete the tests associated with it and you won't loose any test coverage. Kinda long winded but that's how I would approach testing it.

Resources