【问题标题】:MissingPropertyException thrown in spock test where block在 spock 测试中抛出 MissingPropertyException where block
【发布时间】:2015-10-07 01:20:34
【问题描述】:

我一直在使用 spock 对我的 java 项目进行单元测试,但遇到了问题。我有一个实用方法可以从 http 请求中获取参数,或者如果 http 请求为空,则为空字符串,并且我正在尝试使用 spock 对其进行测试。我的测试如下所示:

package foo.bar.test

import foo.bah.HttpRequestPropertyLoader
import spock.lang.Unroll
import javax.servlet.http.HttpServletRequest
import spock.lang.Specification

class HttpRequestPropertyLoaderTest extends Specification {

    HttpRequestPropertyLoader subjectUnderTest
    def result

    def setup() {
        subjectUnderTest = new HttpRequestPropertyLoader()
    }

    @Unroll("When my http request is #nullOrNot then when I get parameter from it the response=#response" )
    def "Test load data from request"() {
        given:
        HttpServletRequest mockHttpRequest = Mock()
        mockHttpRequest.getAttribute("foo") >> "bar"
        when:
        result = subjectUnderTest.loadStringFromHttpRequest(httpRequest, "foo")
        then:
        result == response
        where:
        httpRequest     | response | nullOrNot
        null            |  ""      | "null"
        mockHttpRequest | "bar"    | "not null"
    }
}

但是,当我运行此测试时,我收到以下错误:

groovy.lang.MissingPropertyException: No such property: mockHttpRequest for class: foo.bar.test.HttpRequestPropertyLoaderTest at foo.bar.test.HttpRequestPropertyLoaderTest.Test load data from request(HttpRequestPropertyLoaderTest.groovy)

经过研究,我了解到where 块在given 块之前运行,因此出现错误,但只是想知道是否有解决方法?

我知道要使用测试外部的变量,我需要使用 @Shared 注释来注释变量,这对我来说似乎是不好的做法。每个测试都应该与其他测试完全分开运行,所以不要真的希望有一个对象在测试之间保持其状态。

是否可以设置 Mock 对象以其他方式从 where 块返回?

【问题讨论】:

  • 您是否尝试在测试开始时将HttpServletRequest mockHttpRequest = Mock() 移动到setup 块?
  • @tim_yates 感谢您的建议。如果这就是您的意思,我只是尝试用设置块替换给定块,并得到相同的结果。
  • 四处搜索,我认为您需要将模拟类移出@Shared 类级别字段
  • @tim_yates 是的,我之前看过 @Shared 注释,但正如其中一个答案所说,'缺点是 a 和 o 在某种意义上定义在错误的范围内,可以由其他特征方法也是如此。正如我在编辑中所说,这对我来说似乎是一种不好的做法,但如果没有其他选择,我将不得不研究它。

标签: unit-testing groovy spock


【解决方案1】:

按照 tim_yates 的建议查看 https://code.google.com/p/spock/issues/detail?id=15#c4,我发现了一个相当优雅的解决方案,它不涉及使用 @Shared 注释。测试定义现在如下所示:

package foo.bar.test

import foo.bah.HttpRequestPropertyLoader
import spock.lang.Unroll
import javax.servlet.http.HttpServletRequest
import spock.lang.Specification

class HttpRequestPropertyLoaderTest extends Specification {

    HttpRequestPropertyLoader subjectUnderTest
    def result

    def setup() {
        subjectUnderTest = new HttpRequestPropertyLoader()
    }

    @Unroll("When my http request is #nullOrNot then when I get parameter from it the response=#response" )
    def "Test load data from request"() {
        when:
        result = subjectUnderTest.loadStringFromHttpRequest(httpRequest, "foo")
        then:
        result == response
        where:
        httpRequest << {
            HttpServletRequest mockHttpRequest = Mock()
            mockHttpRequest.getAttribute("foo") >> "bar"
            [null, mockHttpRequest]
        }()
        response << ["", "bar"]
        nullOrNot << ["null", "not null"]
    }
}

【讨论】:

  • 我猜你可能会将为httpRequest 创建模拟值列表的块移动到单独的static 方法中,并且只在where 块中调用它。那么它应该更干净,更易读,类似于httpRequest &lt;&lt; mockHttpRequest(),其中mockHttpRequest() 是返回[null, mockHttpRequest]的静态方法
猜你喜欢
  • 1970-01-01
  • 2020-05-25
  • 2014-05-10
  • 1970-01-01
  • 2013-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-20
相关资源
最近更新 更多