2012-12-28 45 views
4

我正在研究一个新鲜的Grails项目,并且最近注意到Spring Security Core生成的User类中的默认约定现在通过beforeInsert/Update事件自动编码密码。这是一种干净,干净的编码方式,也使得忘记这么做成为不可能。但是,现在当试图写一些使用所述User类的单元测试时,我发现我必须模拟springSecurityService(由于编码),或者更优选地(并且干净地),我' d只需重写beforeInsert/Update闭包,其中一个不执行任何操作。通常在Groovy一个可以覆盖使用ExpandoMetaClass,鼻翼的方法...Grails GORM领域类的单元测试重写事件关闭

User.metaClass.beforeInsert = { /* do nothing */ } 

...但我发现,原来beforeInsert继续在创建并保存新的用户调用。这反过来导致我的单元测试爆炸。对我来说,解决这个问题并嘲笑服务是微不足道的,但上面的应该工作。我错过了什么吗? GORM的事件关闭有什么不同,我没有采取?

+0

另外一点需要注意的,我有一个@Mock([用户])在我的测试注解。这可能与奇怪的行为有关,但仅仅是一种预感。 – James

+0

是实例上的expando方法吗? //问它永远不会太晚:) –

+0

你为什么这么想,那嘲笑springSecurityService并不是这样做的首选方式?我的意思是,在思考依赖注入时,首先考虑的事情之一就是:外部化依赖管理,因此能够为测试目的创建存根/模拟。在我看来,改变用户的metaClass在任何方面都不是很清楚。 –

回答

3

为了提高性能Grails使用反射直接与缓存方法处理调用事件,而不是Groovy的元层。原因是,如果您要保存数百个域实例,那么如果Grails必须通过Groovy的每个事件的元层才能严重影响性能。

有办法解决这个问题,比如定义你自己的User类,根据你的测试设置的系统/环境属性来禁用事件,但是目前没有办法通过元编程来覆盖这些方法。

+0

我知道这是一个老问题。有什么方法可以访问缓存层来覆盖该方法吗? – christopher

1

beforeInsert闭包实际上不仅是像toString()或save()这样的方法,而且也是Gorm支持的预定义事件。重写该方法不会阻止Gorm触发导致原始过程的PreInsert事件。

+2

我知道beforeInsert是一个事件(参见我的最后一句话),但关闭仅仅决定了当给定模型的事件被触发时*发生了什么。重写它应该允许一个人改变那个行为,就像其他任何东西一样。我并没有试图阻止GORM发起事件,我试图改变事件发生时会发生的事情。 – James

0

如果需要,你可以用一个私有方法替换beforeInsert代码,然后重写私有方法