Reputation: 4436
I have the following class that I want to test
package bsg
class NotificationService {
def create(String publicMsg, String privateMsg = null, Player activePlayer, Player passivePlayer = null) {
new Notification(
game: activePlayer.game, publicMessage: publicMsg, privateMessage: privateMsg,
activePlayer: activePlayer, passivePlayer: passivePlayer
).save(failOnError: true)
}
}
And the following test class
package bsg
import grails.test.mixin.*
import spock.lang.Specification
import spock.lang.Unroll
/**
* See the API for {@link grails.test.mixin.services.ServiceUnitTestMixin} for usage instructions
*/
@TestFor(NotificationService)
@Mock([Notification, Game, Player])
class NotificationServiceSpec extends Specification {
NotificationService service
private static final String HIDDEN_SIDE = "1 - Launch Scout"
private static Player adama
private static Player baltar
private static Game game
private static Card card
private static NotificationService notificationService
def setup() {
service = new NotificationService()
game = new Game(name: "foo").save(validate:false)
card = new Card(hiddenSide: HIDDEN_SIDE, backSide: "Bacon", deck: new Deck(backSide: "Skill Card"))
adama = new Player(game: game, character:Player.Character.Adama).save(validate: false)
baltar = new Player(game: game, character:Player.Character.Baltar).save(validate: false)
notificationService = service
}
@Unroll
def "test create1"(String privateMsg, Player passivePlayer, Closure serviceMethod) {
when: "I create a notification"
Notification notification = serviceMethod.call()
then: "a notification has been persisted"
notification?.id != null
and: "it displays the correct messages"
notification.publicMessage == "foo"
notification.privateMessage == privateMsg
notification.activePlayer == adama
notification.passivePlayer == passivePlayer
where:
privateMsg | passivePlayer | serviceMethod
"bar" | baltar | { notificationService.create("foo", "bar", adama, baltar) }
null | baltar | { notificationService.create("foo", null, adama, baltar) }
"bar" | null | { notificationService.create("foo", "bar", adama) }
null | null | { notificationService.create("foo", adama) }
}
@Unroll
def "test create2"(String privateMsg, Player passivePlayer, Closure serviceMethod) {
when: "I create a notification"
Notification notification = serviceMethod.call()
then: "a notification has been persisted"
notification?.id != null
and: "it displays the correct messages"
notification.publicMessage == "foo"
notification.privateMessage == privateMsg
notification.activePlayer == adama
notification.passivePlayer == passivePlayer
where:
privateMsg | passivePlayer | serviceMethod
"bar" | baltar | { notificationService.create("foo", "bar", adama, baltar) }
null | baltar | { notificationService.create("foo", null, adama, baltar) }
"bar" | null | { notificationService.create("foo", "bar", adama) }
null | null | { notificationService.create("foo", adama) }
}
}
Both tests are identical, but in "test create1"()
the first 2 tests fail and the second two pass. In "test create2"()
all 4 tests pass. The error message for both failures is this:
Condition not satisfied:
notification.passivePlayer == passivePlayer
| | | |
| Baltar (null) | null
| false
Adama (null) foo to Baltar (null)
at bsg.NotificationServiceSpec.test create1(NotificationServiceSpec.groovy:44)
So it looks like the static class variable baltar
is somehow not set for the first tests. Can someone help me understand what's going on?
Upvotes: 0
Views: 699
Reputation: 4436
Well, funny story... I'm at the NFJS RWX/CDX conference and immediately after posting this question I got in the elevator with Peter Niederwieser. He had me sorted out by the time we got to the bottom floor.
It makes perfect sense if you stop to think about it for a minute. I'm sure I'll get the specifics wrong, but my basic understanding is that Spock builds the actual junit test methods from the data tables before the setup()
method executes. Thankfully, using the setupSpec()
will accomplish what I'm looking for.
So this is what I did to fix it. Thanks, Peter.
...
private static final String HIDDEN_SIDE = "1 - Launch Scout"
private static Player adama
private static Player baltar
private static Game game
private static Card card
private static NotificationService notificationService
def setup() {
notificationService = new NotificationService()
game.save(validate:false)
adama.save(validate: false)
baltar.save(validate: false)
}
def setupSpec() {
game = new Game(name: "foo")
card = new Card(hiddenSide: HIDDEN_SIDE, backSide: "Bacon", deck: new Deck(backSide: "Skill Card"))
adama = new Player(game: game, character:Player.Character.Adama)
baltar = new Player(game: game, character:Player.Character.Baltar)
}
...
Peter said he would jump on and answer this later, I'm sure that he'll have a MUCH better explanation. Hopefully, he'll have time; and I will accept his answer if he does.
Upvotes: 1