【问题标题】:Access variables inside methods in a Spock Testing在 Spock 测试中访问方法内的变量
【发布时间】:2018-03-19 21:55:46
【问题描述】:

在 Spock 测试中,我希望能够更改方法内变量的值。
例如,我想将 uName 的值更改为“John”。或者对于另一个测试,在进行测试时将 uCat 的值更改为“seller”。如何在测试中确保执行 else 语句中的两种方法:postComment 和 sendEmails。

class userService {

    void userComment()
    {
        def uName = "test123"   
        def uCat = Category.getUserCategory(uName)

        if (uCat.empty){    
            println("no categories to process")
        }
        else
        {
            postComment(uName)
            batchJob.sendEmail(uName)   
        }
    }
}



class userServiceSpec extends Specification{
    def "test userComment"()
    {   
        given:
        ?????

        when:   
        ?????

        then:
        1 * postComment(_)

        then:
        1* batchJob.sendEmail(_)
    }
}

【问题讨论】:

  • 对你来说坏消息:你不能在测试中改变局部变量——你不应该!类或方法应该是测试的黑匣子。重新设计您的应用程序以进行解耦和dependency injection,然后您可以只注入用户名或批处理作业等依赖项。问题不在于测试,而在于应用程序不可测试,因为它在内部创建了自己的依赖项,而不是注入它们。

标签: java unit-testing mocking spock stub


【解决方案1】:

对于uName,您需要将用户名作为构造函数参数注入或在服务中添加方法参数。方法参数可能最有意义。

因为您将getUserCategory 设为静态方法,所以您必须使用GroovySpy,但这通常表明您做错了什么。你真的应该把CategoryService 注入你的userService

class userService {

    void userComment(uName)
    {  
        def uCat = Category.getUserCategory(uName)

        if (uCat.empty){    
            println("no categories to process")
        }
        else
        {
            postComment(uName)
            batchJob.sendEmail(uName)   
        }
    }
}


class userServiceSpec extends Specification{
    def userService = Spy(userService)
    def CategorySpy = GroovySpy(Category, global: true)

    def "test userComment"()
    {   
        given:
        def uName = "test123"  

        when: 'we have a category found'  
        userService.userComment(uName)

        then: 'return user cat of "seller" '
        1 * CategorySpy.getUserCategory(uName) >> 'seller'
        1 * postComment(uName)

        then:
        1 * batchJob.sendEmail(uName)

        when: 'we have an "empty" category'  
        userService.userComment(uName)

        then: 'return a category where uCat.empty will be true'
        1 * CategorySpy.getUserCategory(uName) >> []
        0 * postComment(uName)
        0 * batchJob.sendEmail(uName)
    }
}

一些可能有帮助的Spock Framework slides

综上所述,您确实应该重构以使您的类更易于测试。依赖注入是你的朋友。永远不要在这样的类中硬编码值。

【讨论】:

  • 谢谢。这就是我一直在寻找的。想知道您为什么使用 Spy v GroovySpy。另外,为什么是 Spy v Mock 或 Stub?
  • GroovySpy 用于特殊情况,例如模拟您可能无法控制的创建的静态方法、构造函数和实例。一般来说,您确实不需要它,但鉴于您使用静态方法来获取用户类别,因此它是必需的。这就是为什么你不应该使用静态方法——它使模拟变得更加困难。
  • @CChang 您使用 Mocks 来控制所有方法调用,或者默认情况下从方法返回 null。当你想为大多数事情使用一个类的 real 方法实现,但你想重写和/或验证一个真正实现的方法时,请使用 Spy。我从不使用存根。也很少需要使用 Spy。
猜你喜欢
  • 2018-11-30
  • 1970-01-01
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-22
  • 2014-08-21
  • 1970-01-01
相关资源
最近更新 更多