0

I have a grails application with a service called MySampleservice.groovy in grails-app/services/com/myapp/

The service has a method:

boolean spockTest() {
    return false;
}

I've added this in my BuildConfig.groovy

    test(":spock:0.7") {
        exclude "spock-grails-support"
    }

Question

  • How/Where should I write a spock test for this service?
  • How would I run it?
birdy
  • 9,286
  • 24
  • 107
  • 171
  • 1
    Start from [here](http://grails.org/doc/latest/guide/testing.html). You should be able to write one easily. – dmahapatro Jun 19 '14 at 17:40

2 Answers2

0

A simple service:

// grails-app/services/com/myapp/MySampleService.groovy
package com.myapp

class MySampleService {

    def someMethod(String arg) {
        arg?.toUpperCase()
    }
}

A Spock Spec for that service:

// test/unit/com/myapp/MySampleServiceSpec.groovy
package com.myapp

import grails.test.mixin.TestFor
import spock.lang.Specification

@TestFor(MySampleService)
class MySampleServiceSpec extends Specification {

    void "test someMethod"() {
        expect:
        service.someMethod(null) == null
        service.someMethod('Thin Lizzy') == 'THIN LIZZY'
    }
}

You can run the test with grails test-app unit:.

You didn't mention what version of Grails you are using. With 2.4.0 you won't need to make any mention of Spock in your BuildConfig.groovy in order for that to work.

Jeff Scott Brown
  • 26,804
  • 2
  • 30
  • 47
  • Your comment says `grails test-app unit`. Mine says `grails test-app unit:`. Did you leave the colon off just in the comment or is that what you actually ran? Without the colon, I don't expect that to work. – Jeff Scott Brown Jun 19 '14 at 20:30
  • Your comment disappeared as I added that one. There was a comment here that said that the command didn't work and it cited `grails test-app unit` as the command that was entered. – Jeff Scott Brown Jun 19 '14 at 20:31
  • I am on grails 2.2.4. Following your answer, my tests are still not being executed. Tried the following `grails test-app unit:` `grails test-app unit:spock` and `grails test-app :spock` but with all the three I get message `Tests Passed` but the report says `No tests executed`. I've even intentionally made the tests fail yet it says `Tests Passed` because they are never ran... – birdy Jun 19 '14 at 20:31
  • Sorry, I had lot of comments and then I deleted them to add one comment explaining all that I've tried. appreciate your help – birdy Jun 19 '14 at 20:32
  • I just created a 2.2.4 app and pasted those classes directly from the browser here into the project and the test works. See https://github.com/jeffbrown/birdy which includes both a Spock Spec and a JUnt test for the service. If you run `grails test-app unit:` the tests run and pass. If you change assertions in the tests or change the service code, the tests fail. – Jeff Scott Brown Jun 19 '14 at 20:43
  • Make sure your BuildConfig is configured correctly. Your description mentions the spock plugin but doesn't mention the separate org.spockframework:spock-grails-support:0.7-groovy-2.0 dependency. You want something like https://github.com/jeffbrown/birdy/blob/8ef535a7b0f3d983c7634d8e8b8973b352ca8c62/grails-app/conf/BuildConfig.groovy#L42 in order for this to work with 2.2.4. – Jeff Scott Brown Jun 19 '14 at 20:45
  • *sigh* looks like I must have messed something up in my project files. Thanks a log for your help. I'll compare my project files with the project you posted. – birdy Jun 19 '14 at 20:45
  • I have that dependency as well. But I have several other dependencies as well. I'll remove stuff one by one and try to narrow down what is going on – birdy Jun 19 '14 at 20:53
  • Make sure your tests are defined under `test/unit`, make sure the file names match the class names and that kind of stuff. It sounds like you have something wrong such that Grails can't find your tests, but without having the code it is hard to say what it might be. If I could see it, it would be a 30 second mission to fix it. If you can reproduce in a project you can share, let me know. – Jeff Scott Brown Jun 19 '14 at 21:01
  • You can go down the route of eliminating dependencies and maybe that will help, but I think that is unlikely to be the problem. Hard to say without having it in front of me though. – Jeff Scott Brown Jun 19 '14 at 21:04
  • Were you able to get it sorted out? – Jeff Scott Brown Jun 20 '14 at 13:58
  • Yeah, I was able to. looked at everything with fresh set of eyes and i was missing the `extends Specification` and I hate myself for it. Thanks for your time and patience! – birdy Jun 20 '14 at 14:17
  • Doh! Now I am face palming. When I listed a few simple things like file names and test directory names it actually occurred to me to mention that as well, but I didn't. Anyway, I am glad you got it sorted out. – Jeff Scott Brown Jun 20 '14 at 14:18
  • Off topic. I would love your input on converting grails app to OSGi bundle http://stackoverflow.com/questions/24326118/is-it-possible-to-convert-a-simple-grails-application-to-osgi-bundle-that-can-ru. I know the core team decided to not proceed with OSGi support but wondering if its still feasible. I worked on a grails app for ~6 months but now because of business decisions we have to make it so it can run under Adobe CQ. I would hate to lose all the work I've done in grails. – birdy Jun 20 '14 at 14:19
  • I decided quite a long time ago that it didn't make sense for me to invest effort into OSGi. I am sorry that I can't help you with that. – Jeff Scott Brown Jun 20 '14 at 14:22
  • I feel the same. Its a dated thing to work on and I hate the entire ecosystem. modularity makes sense architecturally but its god awful. Anyways, thanks! – birdy Jun 20 '14 at 14:28
0

Your are not doing any thing in your service method, you can test it as

@TestFor(MySampleService)
class MySampleServiceSpec extends Specification {

    def setup() {
    }

    def cleanup() {
    }

    void "test something"() {
        when:
        def result = service.spockTest()

        then:
        assert result == false
    }
}

A service is generally used for database interaction, such as saving the data, lets take a simple example, following is my service method

Comment spockTest(String comment) {
    Comment commentInstance = new Comment(comment: comment).save()
    return commentInstance
}

then I generally test this as

@TestFor(MySampleService)
@Mock([Comment])
class MySampleServiceSpec extends Specification {

    def setup() {
    }

    def cleanup() {
    }

    void "test something"() {
        given:
        Integer originalCommentCount = Comment.count()

        when:
        def result = service.spockTest('My Comment')

        then:
        assert originalCommentCount + 1 == Comment.count()
        assert result.comment == "My Comment"
    }
}

Where Comment is my domain class.

I run this test as grails test-app -unit MySampleServiceSpec

MKB
  • 7,587
  • 9
  • 45
  • 71
  • 2
    You really shouldn't use assertions like that in a Spock Spec. In the `then:` block instead of `assert result.comment == "My Comment"` the normal thing to do is just `result.comment == "My Comment"`. – Jeff Scott Brown Jun 19 '14 at 18:42