Grails 2.4.5中如何模拟带复合ID的MyObject对象?
解决Grails中复合ID对象的单元测试模拟问题
我之前也踩过Grails里复合ID对象单元测试mock的坑,你的问题核心是mockDomain默认对复合主键的支持不够友好,导致查询不到模拟数据。给你两个靠谱的解决办法:
方法一:手动创建并保存对象(推荐)
放弃直接在mockDomain里传数据列表,先初始化mock,再手动创建对象并执行保存操作,让模拟ORM层正确处理复合ID的逻辑:
def setup() { // 先初始化mockDomain mockDomain(MyObject) // 手动创建对象并保存,flush确保数据立即写入模拟库 new MyObject( action: 'ACT1', reason: 'REAS1', description: 'First reason' ).save(flush: true, failOnError: true) new MyObject( action: 'ACT2', reason: 'REAS2', description: 'Second reason' ).save(flush: true, failOnError: true) // 现在查询就能拿到数据了 def myObject = MyObject.first() }
添加failOnError: true还能帮你快速排查保存失败的问题(比如字段约束不满足之类的)。
方法二:显式指定复合ID的映射
如果一定要用mockDomain的列表参数,需要在每个数据map里显式指定id字段,值为包含复合主键字段的map:
def setup() { mockDomain(MyObject, [ [ id: [action: 'ACT1', reason: 'REAS1'], action: 'ACT1', reason: 'REAS1', description: 'First reason' ], [ id: [action: 'ACT2', reason: 'REAS2'], action: 'ACT2', reason: 'REAS2', description: 'Second reason' ] ]) def myObject = MyObject.first() }
这样mockDomain才能正确识别复合主键,后续的first()、findAll()查询才能匹配到数据。
为什么原来的写法不行?
Grails的mockDomain默认是针对单主键对象设计的,它不会自动识别你在domain类里定义的composite: ["action", "reason"]配置,所以直接传的列表数据,模拟ORM层没法把action和reason当作主键来构建查询条件,自然查不到数据。
内容的提问来源于stack exchange,提问作者mcvkr
相关产品推荐
相关产品推荐

