【问题标题】:Strange behaviour in Grails' Integration TestsGrails 集成测试中的奇怪行为
【发布时间】:2013-03-23 19:19:01
【问题描述】:

我正在 IBM(here) 上做 Grails 教程,但我对集成测试感到非常失望。 总结:我调用了一个根据ID(iata)渲染JSON对象的方法。

我的域名是:

 class Airport {        
    String name
    String iata
}

我的控制器是:

class AirportController {

    // In order to enable scaffolding
    def scaffold = Airport

    def iata = {
        def iata = params.id?.toUpperCase() ?: "NO IATA"
        def airport = Airport.findByIata(iata)
        if (!airport) {
            airport = new Airport(iata: iata, name: "Not found")
        }

        render airport as JSON
    }    
}

当我这样做时: http://localhost:8080/trip-planner/airport/iata/foo(为了检索空值)或 http://localhost:8080/trip-planner/airport/iata/DEN(针对 DENVER),该方法运行良好!

问题是我的集成测试:

class AirportControllerTests extends GroovyTestCase {
    void testWithGoodIata(){
        def controller = new AirportController()
        controller.metaClass.getParams = { ->
        return ["id":"den"]
        }

        controller.iata()

        def response = controller.response.contentAsString
        assertTrue response.contains("Denver")
    }

    void testWithWrongIata() {
        def controller = new AirportController()
        controller.metaClass.getParams = { ->
        return ["id":"foo"]
        }

        controller.iata()

        def response = controller.response.contentAsString
        assertTrue response.contains("\"name\":\"Not found\"")      
    }
}

问题是:

每当我运行测试时(通过运行:grails test-app -integration trip.planner.AirportControllerTests),我总是会在第一个测试中获得良好的行为,并在 第二个 测试中获得groovy.lang.MissingMethodException。 (即使我切换两者:第二次测试总是失败)

如果我单独运行它们,它可以工作。 异常发生在这一行(在控制器中):def airport = Airport.findByIata(iata)

这与“交易”有关吗?任何帮助都会很棒:)

P.S : 我使用的是 Grails 2.2.1

异常堆栈跟踪:

groovy.lang.MissingMethodException: No signature of method: trip.planner.Airport.methodMissing() is applicable for argument types: () values: []
    at trip.planner.AirportController$_closure4.doCall(AirportController.groovy:39)
    at trip.planner.AirportControllerTests.testWithWrongIata(AirportControllerTests.groovy:25)

【问题讨论】:

  • 几个可能会改进您的代码(并且可能有助于解决问题)的问题:为什么查询数据库的逻辑在控制器内部?如果没有业务逻辑,您应该能够在单元测试中测试控制器行为,单元测试只负责处理请求和响应。其次,不要使用假身份证来查找机场,只需使用 null 而不是 'NO IATA'。
  • 为什么逻辑在控制器内部?控制器必须执行逻辑,这就是它在这里的原因(我只是在做 IBM 的教程)。我将“NO IATA”替换为 null,但这并不能解决问题。
  • 对不起,我没有很好地解释自己。逻辑当然是必需的,但它应该存在于服务中,而不是控制器中。
  • 是的,对,所以你认为我必须创建一个服务(我的控制器调用)?这只是改进,我不寻找这个(这是一个教程......),我认为它不会解决我的问题,它只会改变它。

标签: grails integration-testing missingmethodexception


【解决方案1】:

我怀疑您在一个测试中所做的元类更改会以某种方式泄漏到另一个测试中。但是您不需要(也不应该)在 集成 测试中操作元类,只需说

def controller = new AirportController()
controller.params.id = "den"

你只需要为 unit 测试做模拟。

请记住,您正在查看的教程写于 2008 年(在 Grails 1.0.x 时代),从那时起 Grails 已经走了很长一段路,其中一些组件(包括测试)具有经历过一次或多次完全重写。

【讨论】:

  • 谢谢,我可能需要再找一个教程...
  • @GuillaumeM 您可以编辑问题以包含MissingMethodException 的完整详细信息(和堆栈跟踪)吗?显然缺少哪个方法,谁在尝试调用它?
  • 完成。这很奇怪,因为我在两个测试中都调用了完全相同的方法。
  • @GuillaumeM 这很奇怪,我唯一一次看到像这样的莫名其妙的 MME 是当我没有在我的应用程序中安装休眠插件时,它一直在失败而不是而不仅仅是第二次通话。您可以在未过滤的堆栈跟踪(stacktrace.log)中找到更多信息,其中包括更多 Groovy 内部堆栈帧。但大多数情况下是的,我会说寻找为 Grails 2 编写的更新的教程。
  • 我找到了未过滤的堆栈跟踪。怕是这里就不复制粘贴了,因为要401行!
猜你喜欢
  • 1970-01-01
  • 2017-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多