【问题标题】:Grails controller unit tests with Joda Time使用 Joda Time 进行 Grails 控制器单元测试
【发布时间】:2013-07-20 12:34:40
【问题描述】:

当我有一个带有 Joda LocalDateTime 字段的域对象时,一些生成所有创建的控制器测试失败。

$ grails create-app bugdemo
$ cd bugdemo
$ grails create-domain-class Item

编辑 grails-app/domain/bugdemo/Item.groovy

package bugdemo
import org.joda.time.LocalDateTime

class Item {
    String name
    // LocalDateTime opening
    static constraints = {
        name blank:false
    }
}

将以下行添加到 BuildConfig.groovy

compile ":joda-time:1.4"

在命令行继续

$ grails compile
$ grails install-joda-time-templates
$ grails generate-all bugdemo.Item
$ grails test-app *ItemController

报告了几个错误。通过编辑 ItemControllerTests 的 TODO 区域来修复这些问题

def populateValidParams(params) {
    assert params != null
    // TODO: Populate valid properties like...
    //params["name"] = 'someValidName'
    params["name"] = "Name"
}

   // test invalid parameters in update
    params.id = item.id
   //TODO: add invalid values to params object
    params.name = ""

现在所有控制器测试都通过了。

现在取消注释 Item.groovy 中的 LocalDateTime 字段。那些控制器测试不再通过。我假设我需要添加更多参数来填充打开对象。但是传递了什么参数呢?如果我运行应用程序,我可以查看表单并看到以下字段和值:

name: "Some Name"
opening: "struct" (hidden)
opening_day: "20"
opening_month: "7"
opening_year: "2013"
opening_hour: "22"
opening_minute: "20"

所以我修改闭包populateValueParams中的代码如下:

def populateValidParams(params) {
    assert params != null
    // TODO: Populate valid properties like...
    //params["name"] = 'someValidName'
    params["name"] = "Name"
    params["opening"] = "struct"
    params["opening_day"] = "20"
    params["opening_month"] = "07"
    params["opening_year"] = "2013"
    params["opening_hour"] = "22"
    params["opening_minute"] = "20"
}

当我运行测试时,错误仍然存​​在。似乎没有正确保存 Item 对象,大概是因为 LocalDateTime 字段在测试环境中没有正确填充(即使它在开发环境中)。

$ grails test-app *ItemController

| Running 8 unit tests... 2 of 8                                                            
| Failure:  testShow(bugdemo.ItemControllerTests)                                           
|  Assertion failed:                                                                        

assert item.save() != null                                                                  
       |    |      |                                                                        
       |    null   false                                                                    
       bugdemo.Item : (unsaved)                                                             

        at bugdemo.ItemControllerTests.testShow(ItemControllerTests.groovy:69)              
| Running 8 unit tests... 3 of 8                                                            
| Failure:  testSave(bugdemo.ItemControllerTests)                                           
|  Assertion failed:                                                                        

assert response.redirectedUrl == '/item/show/1'                                             
       |        |             |                                                             
       |        null          false                                                         
       org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletResponse@d67c36      

        at bugdemo.ItemControllerTests.testSave(ItemControllerTests.groovy:55)              
| Running 8 unit tests... 6 of 8                                                            
| Failure:  testEdit(bugdemo.ItemControllerTests)                                           
|  Assertion failed:                                                                        

assert item.save() != null                                                                  
       |    |      |                                                                        
       |    null   false                                                                    
       bugdemo.Item : (unsaved)                                                             

        at bugdemo.ItemControllerTests.testEdit(ItemControllerTests.groovy:87)              
| Running 8 unit tests... 7 of 8                                                            
| Failure:  testUpdate(bugdemo.ItemControllerTests)                                         
|  Assertion failed:                                                                        

assert item.save() != null                                                                  
       |    |      |                                                                        
       |    null   false                                                                    
       bugdemo.Item : (unsaved)                                                             

        at bugdemo.ItemControllerTests.testUpdate(ItemControllerTests.groovy:107)           
| Running 8 unit tests... 8 of 8                                                            
| Failure:  testDelete(bugdemo.ItemControllerTests)                                         
|  Assertion failed:                                                                        

assert item.save() != null                                                                  
       |    |      |                                                                        
       |    null   false                                                                    
       bugdemo.Item : (unsaved)                                                             
| Packaging Grails application.....                                                         

Joda 类的某些方面是否需要模拟?当控制器说

    def itemInstance = new Item(params)

为什么它在开发中有效,但在测试中无效? 它在开发中是如何工作的?

我正在使用 Grails 2.2.3、Java 1.7.0_25、Windows 7。

【问题讨论】:

    标签: unit-testing grails controller jodatime


    【解决方案1】:

    单元测试不会自动设置自定义属性编辑器(负责转换域类实例中提交的信息)。

    查看来源,似乎JodaTimePropertyEditorRegistrar对此负责。所以在你的测试中你可以使用defineBeans来添加这个Spring Bean:

    import grails.plugin.jodatime.binding.JodaTimePropertyEditorRegistrar
    
    class MyTest {
      @Before
      public void setup() {
        defineBeans {
          jodaTimePropertyEditorRegistrar(JodaTimePropertyEditorRegistrar)
        }
      }
    }
    

    【讨论】:

    • 感谢塞尔吉奥!完美诊断,完美解决方案。
    • 酷!我很乐意帮助你:-)
    【解决方案2】:

    您可以使用对象在 populateValidParams() 方法中设置 DateTime() 或其他 joda-time 值...

    def populateValidParams(params) {
        assert params != null
        params["name"] = "Name"
        params["opening"] = new DateTime()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-14
      • 1970-01-01
      • 2014-08-07
      • 2017-04-26
      • 1970-01-01
      • 2015-07-12
      相关资源
      最近更新 更多