Nutel
Nutel

Reputation: 2294

Classical unit test as Groovy Spock method

I have a Groovy Spock method that has the following pattern:

def "My test"() {
  def a = createA();
  assert a.fieldLevel1.isValid()
  def b = a.fieldLevel1
  assert b.fieldLevel2.isValid()
  def c = b.fieldLevel2
  assert c.fieldLevel3.isValid()
  ...
}

As you can see it's hard to break it on blocks as assertions and variables definitions are mixed together. What would be the "spock" approach to write such kind of test?

UPDATE:

The test has the following structure because c.fieldLevel3.isValid() is actually c.fieldLevel3 instanceof A, so I can't proceed if the field is invalid.

Upvotes: 1

Views: 543

Answers (2)

JoeG
JoeG

Reputation: 7642

Not sure why you did not accept the answer above it looks quite good.

As a minor difference, you could also do:

def "My test of creating an A"() {
    when: 
        def a = createA()
    then: 
        a.fieldLevel1.isValid()
        a.fieldLevel1.fieldLevel2.isValid()
        a.fieldLevel1.fieldLevel2.fieldLevel3.isValid()
}

Whether or not you 'like' this depends upon how closely you follow Demeter's 'Law' - Groovy seems to make that less relevant than in the past.

If the complexity of the actual underlying objects is such that this is not an effective approach at validating them, then they might deserve their own Unit Tests.

Upvotes: 1

epidemian
epidemian

Reputation: 19219

The "classical" way of unit testing is keeping tests unitary. That is, testing one thing per test, which seems not to be the case in this example.

That being said, however, you could group all the assertions in an expect block after all the setup code in a setup block:

def "My test"() {
  setup:
  def b = createA().fieldLevel1
  def c = b.fieldLevel2
  def d = c.fieldLevel3
  expect:
  b.valid
  c.valid
  d.valid
}

Notice that i've shortened the assertions by using Groovy's goodies to access isValid() as valid and calling that method on the auxiliary objects directly.

Also, i haven't used the usual when/then Spock blocks because this test case doesn't seems to align very well with being a stimuli/response on a given system. But you could also use many when and then alternated blocks if you so desire:

def "My test"() {
  when: def b = createA().fieldLevel1
  then: b.valid
  when: def c = b.fieldLevel2
  then: c.valid
  when: def d = c.fieldLevel3
  then: d.valid
}

Upvotes: 4

Related Questions