【问题标题】:groovy / grails / unit testing / createCriteria.getgroovy / grails / 单元测试 / createCriteria.get
【发布时间】:2011-04-12 20:22:33
【问题描述】:

我可以模拟调用:

MyDomainClass.createCriteria().list{
    eq('id',id)
    eq('anotherParameter',anotherParameterId)
}

与:

def myCriteria = [
    list : {Closure  cls -> returnThisObject}
]
MyDomainClass.metaClass.static.createCriteria = { myCriteria }

建议:

http://davistechyinfo.blogspot.com/2010/01/mocking-hibernate-criteria-in-grails.html

但对于:

MyDomainClass.createCriteria().get{
    eq('id',id)
    eq('anotherParameter',anotherParameterId)
}

这种方法失败了——可能是因为 'get' 是一个关键字,而 'list' 不是。任何人都可以建议 - 能够在域类中模拟它应该是可能的,而不是简单地放弃使用 createCriteria().get{} 的方法的单元测试覆盖率。

非常感谢您的建议,

亚历克斯

【问题讨论】:

    标签: grails groovy mocking hibernate-criteria


    【解决方案1】:

    现在使用GrailsUnitTestCase.mockDomain1 方法应该会简单得多。

    grails-app/domain/sandbox/grails/foo/Something.groovy

    package sandbox.grails.foo
    
    class Something {
        String name
    }
    

    test/unit/sandbox/grails/foo/SomethingTests.groovy

    package sandbox.grails.foo
    
    import grails.test.mixin.*
    import org.junit.*
    
    @TestFor(Something)
    class SomethingTests {
    
        void testSomething() {
    
            mockDomain(Something, [
                new Something(name: 'Foo'),
                new Something(name: 'Bar'),
                new Something(name: 'Boo'),
                new Something(name: 'Baz')
            ])
    
            def actuals = Something.createCriteria().list(sort: 'name', order: 'asc') {
                like('name', '%oo')
            }
    
            assertEquals 2, actuals.size()
    
        }
    }
    

    【讨论】:

    • 肯定是从 Grails 2.0 开始,但我确实记得在 1.8.x 中也使用过它。
    【解决方案2】:

    我找到了一个不会影响我编写单元测试能力的解决方案 -

    def myCriteria = new Expando();
    myCriteria .get = {Closure  cls -> returnThisObject}         
    MyDomainClass.metaClass.static.createCriteria = {myCriteria }

    这正是我想要的,并且可能支持测试提供的参数。感谢其他回复。希望这对其他测试 domain/createCriteria() 方法的人有用。

    【讨论】:

      【解决方案3】:

      我不会打扰。而是在您的域类中创建方法并模拟这些方法。这使得测试更容易,但更重要的是具有将持久性保持在它所属的位置而不是将其分散在整个代码库中的优势:

      class MyDomainClass {
         String foo
         int bar
      
         static MyDomainClass findAllByIdAndAnotherParameter(long id, long anotherParameterId) {
            createCriteria().list {
               eq('id',id)
               eq('anotherParameter',anotherParameterId)
            }
         }
      
         static MyDomainClass getByIdAndAnotherParameter(long id, long anotherParameterId) {
            createCriteria().get {
               eq('id',id)
               eq('anotherParameter',anotherParameterId)
            }
         }
      }
      

      然后在您的测试中,将其模拟为

      def testInstances = [...]
      MyDomainClass.metaClass.static.findAllByIdAndAnotherParameter = { long id, long id2 ->
         return testInstances
      }
      

      和

      def testInstance = new MyDomainClass(...)
      MyDomainClass.metaClass.static.getByIdAndAnotherParameter = { long id, long id2 ->
         return testInstance
      }
      

      【讨论】:

      • 我已将其简化为:
      • String hello = "hello" def map = [get1:{Closure cls -> hello}, address:"somewhere"] print map.get1{}
      • String hello = "hello" def map = [get:{Closure cls -> hello}, address:"somewhere"] print map.get{}
      • 不同之处在于,当映射键为 'get1' 时,打印 map.get1{} 会打印“hello”,但当键为 'get' 时,则返回 null。也许“get”是一种语言冲突,所以我需要一种完全不同的方法来模拟 createCriteria().get{}。
      • 这是一个比第一个更好和更干净的解决方案,因为域类应该只知道内部而不是客户端
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-23
      • 2010-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多