【问题标题】:Grails dynamic finder where field name contains reserved words字段名称包含保留字的 Grails 动态查找器
【发布时间】:2011-01-30 23:55:05
【问题描述】:

所以我有一个 grails 域类:

class Message
{
    Inbox inbox
    Boolean hasBeenLogicallyDeletedByRecipient
    ...

    static belongsTo = [
        inbox:Inbox,
        ...
    ]

    static constraints = {
        hasBeenLogicallyDeletedByRecipient(nullable:false)
        ...
    }
}

我想使用如下动态查找器:

def messages = Message.findAllByInboxAndHasBeenLogicallyDeletedByRecipient(
                    inbox, false, [order:'desc',sort:'dateCreated'])

在 STS 2.6.0.M1 中针对 grails 1.2.1 运行单元测试用例可以正常工作; 启动 Web 应用程序时,由于 hasBeenLogicallyDeletedByRecipient 中的 By 失败(我猜它在构建查询时混淆了动态查找器解析)。

我可以使用适用于应用程序的标准生成器:

    def messages = Message.withCriteria {
        and {
            eq('inbox', inbox)
            eq('hasBeenLogicallyDeletedByRecipient', false)
        }
        order('dateCreated', 'desc')
    }

但是由于withCriteria 没有被模拟,它不会立即在单元测试中起作用,所以我可以在单元测试中添加以下内容:

    Message.metaClass.static.withCriteria = { Closure c ->
        ...
    }

标准/单元测试是否模拟了最佳/公认的方法?我对嘲笑这一点并不完全满意,因为它回避了测试标准闭包。

理想情况下,我宁愿使用动态查找器 - 有没有一种简洁的方法可以让它按原样工作? 如果没有办法,我想可以更改字段名称​​(我不想这样做是有原因的,但这与问题无关)......

更新:

这是我尝试在应用程序中使用 findAllByInboxAndHasBeenLogicallyDeletedByRecipient() 时的堆栈跟踪 - 注意它似乎如何获取最后一个 By 并将它与 findAll 之间的所有其他内容视为一个财产。我在http://grails.org/OperatorNamesInDynamicMethods 上吃草,但它没有提到任何关于 By 被禁止的事情。

org.codehaus.groovy.grails.exceptions.InvalidPropertyException: No property found for name [byInboxAndHasBeenLogicallyDeleted] for class [class xxx.Message]
    at xxx.messages.yyyController$_closure3.doCall(xxx.messages.yyyController:53)
    at xxx.messages.yyyController$_closure3.doCall(xxx.messages.yyyController)
    at java.lang.Thread.run(Thread.java:662)

【问题讨论】:

    标签: grails groovy hql


    【解决方案1】:

    测试数据库查询实际上是集成测试,而不是单元测试。您的测试是在 /test/unit 还是 /test/integration 中? - 我希望“withCriteria”在集成测试中能够完全发挥作用,但在单元测试中却不行。

    来自 grails 文档 (http://grails.org/doc/latest/),第 9.1 节:

    单元测试是“单元”的测试 等级。换句话说,您正在测试 单独的方法或代码块 不考虑周边 基础设施。在 Grails 中,您需要 特别注意 单位和单位的区别 集成测试,因为在单元中 测试 Grails 不注入任何 过程中出现的动态方法 集成测试和运行时。

    【讨论】:

    • 这是一个单元测试(/test/unit)。如果我拼错 Message.findAllByInboxAndHasBeenLogicallyDeletedByRecipient(...),则针对动态查找器的单元测试将失败,但如果我使用标准并拼错 eq('hasBeenLogicallyDeletedByRecipient', false),则不会失败。虽然我猜它会在集成测试中。
    • @rhu:简而言之,正如保罗指出的那样,您不能在单元测试中使用动态查找器,因为当时 Grails 没有注入它。换句话说,findAllByConstraint 在单元测试中是未定义的。
    • @Hoàng Long:如果我在测试设置中使用来自 GrailsUnitTestCase 的 mockDomain(Message, testData) 和一些单元测试数据,则注入 一些 动态查找器 - 但不是全部;至关重要的是 findAllByInboxAndHasBeenLogicallyDeletedByRecipient() 是并按预期响应,但基本的 findAll() 和 withCriteria() 不是。
    • 在 grails 文档中,隐藏在 9.1 的深处,它说:“谢天谢地,mockDomain() 方法提供了由域实例列表支持的动态查找器的轻量级实现。只需将测试数据提供为该方法的第二个参数和模拟查找器将正常工作。” - 这是我在单元测试中使用的,它们工作得很好,但是在应用程序中注入相同的方法时必须以不同的方式实现,因为它们严重损坏,请参阅我在问题中的更新 - 抱歉应该更清楚...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    相关资源
    最近更新 更多