Unit testing Grails2.1单元测试命令对象mockForConstraintsTests不工作?

Unit testing Grails2.1单元测试命令对象mockForConstraintsTests不工作?,unit-testing,grails,mocking,constraints,Unit Testing,Grails,Mocking,Constraints,我对这个命令对象使用了手动编写的以及Grails生成的单元测试: package myapp @grails.validation.Validateable class SearchCommand { String basisBuild String buildToSearch static constraints = { basisBuild(blank: false) } } 在手

我对这个命令对象使用了手动编写的以及Grails生成的单元测试:

   package myapp

    @grails.validation.Validateable
    class SearchCommand {
       String basisBuild
       String buildToSearch

       static constraints = {
          basisBuild(blank: false)
       }
    }
在手写单元测试失败后,我使用了Grails:

create-unit-test  myapp.SearchCommand
我填写了单元测试,并断言应该通过模拟约束的每个文档:

package myapp
import static org.junit.Assert.*

import grails.test.mixin.*
import grails.test.mixin.support.*
import org.junit.*

@TestMixin(GrailsUnitTestMixin)
class SearchCommandTests {

    void setUp() {
        mockForConstraintsTests(SearchCommand)
    }

    void tearDown() {
        // Tear down logic here
    }

    void testSomething() {
        SearchCommand commandUnderTest = new SearchCommand()

        commandUnderTest.validate(basisBuild: "")

        assertEquals "blank", commandUnderTest.errors['basisBuild']
    }
}
为什么我会失败?

grails> test-app
| Running 9 unit tests... 9 of 9
| Failure:  testSomething(com.siemens.soarian.sf.gap.SearchCommandTests)
|  java.lang.AssertionError: expected:<blank> but was:<null>
        at org.junit.Assert.fail(Assert.java:93)
grails>testapp
|正在运行9个单元测试。。。第9页,共9页
|失败:testSomething(com.siemens.soarian.sf.gap.SearchCommandTests)
|java.lang.AssertionError:应为:但为:
位于org.junit.Assert.fail(Assert.java:93)
编辑

如果现有版本中提到的补丁已经安装到位(感谢@codelark的帮助),那么适当地使用
validate()
mockForConstraintsTest
应该可以工作。为了从Web应用程序的角度(使用
controller
)测试命令对象,以下信息将非常有用

使用控制器操作测试命令对象:-

命令
对象仅在用作
控制器
中的一个
操作
方法中的参数时才被视为该对象。请参阅(警告注释)。 在操作方法中使用
SearchCommand
,您应该能够
assertEquals

示例:

void testSomething() {
        YourController controller = mockController(YourController) //Or instantiate
        SearchCommand commandUnderTest = new SearchCommand ()
        //Note the usage here. validate() does not take parameters
        commandUnderTest.basisBuild = ''
        commandUnderTest.validate()

        //Call your action
        controller.searchCommandAction(commandUnderTest)

        assert response.text == 'Returned'
        assertEquals "blank", commandUnderTest.errors['basisBuild']
    }
控制器的操作:-

def searchCommandAction(SearchCommand sc){
    render "Returned"
}
注意:

void testSomething() {
        YourController controller = mockController(YourController) //Or instantiate
        SearchCommand commandUnderTest = new SearchCommand ()
        //Note the usage here. validate() does not take parameters
        commandUnderTest.basisBuild = ''
        commandUnderTest.validate()

        //Call your action
        controller.searchCommandAction(commandUnderTest)

        assert response.text == 'Returned'
        assertEquals "blank", commandUnderTest.errors['basisBuild']
    }
没有grails bug的补丁,我们可以在@grails 2.1.4、2.2.0和2.2.1中看到下面的错误

当我只更正
验证
并使用
mockForConstraintTests
而不使用
控制器
操作时,我会收到一个错误:


您使用的
验证方法不正确。您从未在类上设置该字段,因此该字段为空,而不是空。尝试按以下方式更改测试:

void testSomething() {
    SearchCommand commandUnderTest = new SearchCommand()
    commandUnderTest.basisBuild = ""

    assertFalse commandUnderTest.validate()
    assertEquals 'blank', commandUnderTest.errors['basisBuild']
}

Edit:在测试使用
@Validatable
注释的命令类时,还有一个问题。错误评论中有一些变通方法。

我相信我找到了grails支持的方法,可以在grails 2.0中对命令对象进行单元测试。您需要使用ControllerUnitTestMixin提供的mockCommandObject

归功于埃里克


我在回答中已经提到了
validate()
方法更正。此外,在Grails2.x中,
mockForConstraintsTests
必须被
mockDomainObject
(来自
ControllerUnitTestMixins
)替换或实例化(如我的回答所示)。按照您提出的修复方案,将在
assertFalse commandUnderTest.validate()
中得到一个
断言
失败。这是从grails 2.2.1中的一个工作示例中提取的。为什么说在2.x中必须替换
mockForConstraintsTest
?它仍然在未弃用的测试API中,我正试图证明自己跟随您是错误的,但它在2.1.4、2.2.0和2.2.1中从未对我起作用。创建一个全新的项目,创建命令对象,创建测试,运行测试。开导我。:)包含在grails创建应用程序之后需要创建的两个文件。然后,
grails测试app:unit
@dmahapatro我们的结果的差异似乎是由于一个未解决的grails bug造成的。显然,注释和模拟辅助对象之间存在交互问题。请注意,我在pastebin中的代码没有使用注释。我会用更多的细节更新我的答案。我希望我的编辑会有所帮助。我很想知道它的行为会有什么不同。:)