Grails / Spock测试..抛出意外错误

时间:2014-05-06 10:14:41

标签: grails testing spock

使用spock对一个命令对象进行单元测试..我在命令对象中有一行..

一些代码..

   } else { 
      if ((val && obj.part) && obj.transactionType.transactionIsATransfer()) { 
         println "obj.part .. class is ${obj.part.getClass()} .. serial is    ${val.getClass()}" 
         if(! isAValidPartSerialCombo(obj.part,val))  <-- line 79  
             return 'com.myStuff.TransactionDetailCommand.serialReference.not.for.part' 
    } 
.. 

def isAValidPartSerialCombo {part, serialReference -> 
        return InventoryMaster.hasPartandSerial(part,serialReference) 
} 

我有一个单元测试,我在那里模拟了依赖

def obj = new TransactionDetailCommand(transactionType: new TransactionType(type: 'Transfer', requireSerial: true), 
              serialReference: 'AAA', part: new Part(partNumber: 'AAA')) 

      obj.metaClass.isAValidPartSerialCombo = {a,b -> false}

  and: "we try to validate the transaction " 
      obj.validate() 

  then: "we get an error on the transaction for the 'serialReference' property" 
      obj.errors['serialReference'] 

这给了我一个错误..

java.lang.IllegalArgumentException: object is not an instance of declaring class 
        at com.vantec.TransactionDetailCommand._clinit__closure1_closure7(TransactionDetailCommand.groovy:90) 
        at grails.test.MockUtils.addValidateMethod_closure87_closure114(MockUtils.groovy:1035) 
        at grails.test.MockUtils.addValidateMethod_closure87(MockUtils.groovy:1031) 
        at grails.test.MockUtils.addValidateMethod_closure88(MockUtils.groovy:1065) 
        at com.myStuff.transaction.TransactionDetailCommandSpec.Ensure that for issues / transfer transactions then serial/part numbers are required to match .. (TransactionDetailCommandSpec.groovy:79) 

但是,如果我创建一个单独的虚拟测试,它可以正常工作..

def "A simple test  .. "(){ 
    when: 
        def obj = new TransactionDetailCommand() 
        obj.metaClass.isAValidPartSerialCombo = {a,b -> false} 

    then: 'we get a false ..' 
        !obj.isAValidPartSerialCombo(new Part(),"AAA") 
} 

任何人都可以光明吗?

谢谢

完成测试......

  def "Ensure that for issues / transfer transactions then serial/part numbers are required to match .. "(){

          when: "The transaction type indicates a transfer and we supply a serial number and a part .."

              def obj = new TransactionDetailCommand(transactionType: new TransactionType(type: 'Transfer', requireSerial: true),
                      serialReference: '12345', part: new Part(partNumber: 'PartA'))

              obj.metaClass.isAValidPartSerialCombo = {a,b -> false}

          and: "we try to validate the transaction "
              obj.validate()

          then: "we get an error on the transaction for the 'serialReference' property"
              obj.errors['serialReference']

          and: "the error is the correct one .."
              'com.myStuff.TransactionDetailCommand.serialReference.not.for.part' == obj.errors['serialReference']

    }

和我正在测试的约束..

serialReference nullable: true, validator: { val, obj ->

           println "One .. "
           if ((val == null || val.toString().isEmpty()) && obj.transactionType.requireSerial) {
                 println "Two .. "
                return 'com.myStuff.TransactionDetailCommand.serialReference.required'
            } else {
                 println "Three .. "
                if ((val && obj.part) && obj.transactionType.transactionIsATransfer()) {
                    println "Four ..."
                    if(! isAValidPartSerialCombo(obj.part, val)){
                        println("Five .. ")
                        return  'com.myStuff.TransactionDetailCommand.serialReference.not.for.part'
                    }
                }
            }

            return 'oops'
        }



 def isAValidPartSerialCombo = {part, serialReference ->
        println "Six .."
        // return InventoryMaster.hasPartandSerial(part,serialReference)
        return true
    }

println就是这样,我可以看到代码的位置..

2 个答案:

答案 0 :(得分:0)

不确定,但是在创建实例后尝试模拟obj的实例是值得的

mockDomain(TransactionDetailCommand, [obj])

答案 1 :(得分:0)

尝试以这种方式组织您的测试:

def "Ensure that for issues / transfer transactions then serial/part numbers are required to match .. "(){

      given: "The transaction type indicates a transfer and we supply a serial number and a part .."

          def obj = new TransactionDetailCommand(transactionType: new TransactionType(type: 'Transfer', requireSerial: true),
                  serialReference: '12345', part: new Part(partNumber: 'PartA'))

          obj.metaClass.isAValidPartSerialCombo = {a,b -> false}

      when: "we try to validate the transaction "
          obj.validate()

      then: "we get an error on the transaction for the 'serialReference' property"
          obj.errors['serialReference']

      and: "the error is the correct one .."
          'com.myStuff.TransactionDetailCommand.serialReference.not.for.part' == obj.errors['serialReference']

}

因为对象的创建和元编程都是设置动作。