Grails 使用元类.render的spock测试

Grails 使用元类.render的spock测试,grails,groovy,spock,Grails,Groovy,Spock,为了在render(template)中对模型进行集成测试,我使用metaClass.render将模型存储在地图中。但是,地图似乎不适用于“where”块 def renderMap def mmc def setup() { MilestonesMgtController.metaClass.render = { Map map -> renderMap = map } mmc = new MilestonesMgtController() }

为了在render(template)中对模型进行集成测试,我使用metaClass.render将模型存储在地图中。但是,地图似乎不适用于“where”块

def renderMap
def mmc

def setup() {
    MilestonesMgtController.metaClass.render = { Map map ->
        renderMap = map
    }
    mmc = new MilestonesMgtController()
}

void "create a new milestone"() {
    when:
    mmc.params.newName = 'Written Workshop'
    mmc.params.newDeadlineFT = a
    mmc.params.newDeadlinePT = '4'
    mmc.params.newNotificationFT = '7'
    mmc.params.newNotificationPT = '7'
    mmc.newMilestone()

    then:
    renderMap.template == 'milestoneDetails'
    renderMap.model.errorMessages == b

    where:
    a    |  b
    '4'  |  null                      //first test
    '0'  |  'deadlineFT cannot be 0'  //second test
}

“where”块中的第二个测试失败,它表示renderMap为null。如果我改变第一次和第二次测试之间的顺序,结果是相同的。第一轮之后,renderMap似乎为空。你知道代码有什么问题吗?非常感谢

如果你在集成测试中开始类级元分类,你真的会自食其果。与单元测试不同,这些元类更改不会回滚,并且会使测试运行受到元类污染的影响

如果确实需要集成测试,请尝试对控制器实例进行元分类以防止污染。我很好奇这是否能解决你的问题。此外,我倾向于在这种情况下使用@Shared,尽管我不确定这是否绝对必要

@Shared renderMap
@Shared mmc

def setup() {
    mmc = new MilestonesMgtController()
    mmc.metaClass.render = { Map map -> renderMap = map }
}

为什么需要在集成测试中模拟
渲染
?集成规范并不是为了这个目的。虽然我同意这通常不是一个好办法,但在某些情况下,控制器需要进行集成测试。我们曾经能够使用GroovyPagesTestCase基类来处理渲染案例,但在Grails 2.3切换到新的@TestMixin路径进行集成之后,我所知的任何东西都没有真正取代它。我想您可能会争辩说,您想在控制器中进行集成测试的任何东西都应该移动到服务中并进行模拟。@dmahapatro很抱歉,我不熟悉Grails/Groovy,我两周前就开始使用它了。也许你能告诉我一个正确的方法。我想用模板测试模型渲染,所以正如我在上一篇文章中建议的那样,我使用了带有视图[]的单元测试。然而,我的控制器必须从数据库进行查询,并使用服务。这就是我返回集成测试的原因。在单元测试中使用模拟数据和模拟服务是否有问题?@dmahapatro当我使用mockDomain([…])的模拟数据时。保存,返回的数据总是[xxx:未保存]