【问题标题】:Mock a method inside a service class which is under unit test模拟正在单元测试的服务类中的方法
【发布时间】:2014-09-23 14:27:21
【问题描述】:

我有一个服务类,它有两种方法(一种是公共的,另一种是受保护的)。我正在尝试对我的代码进行单元测试。下面是代码sn-p MyServiceClass.groovy

class MyServiceClass {

       public boolean myMethod1() {
            // some code
            boolean success = myMethod2()
            // some code
       }

      public boolean myMethod2() {
          // some logic to return true/false
          return true
      }

}

MyServiceClassTests.groovy

class MyServiceClassTests {

      void testMyMethod1() {
           // unit test code
      }

}

在上面的单元测试代码中,我想模拟 myMethod1() 调用的 myMethod2() 返回结果,即两个方法都在同一个单元测试中的服务类中。如何模拟它并完成工作?

【问题讨论】:

    标签: unit-testing groovy grails-2.0 gunit


    【解决方案1】:

    你当然不能模拟被测类,否则你只是在测试一个模拟。

    你可能会过得更好,将myMethod2() 转移到另一个班级。想想MyServiceClass是不是trying to do too much

    编辑

    您要求的答案不需要移动 myMethod2()

    选项 1

    创建一个新的子类作为被测类而不是 MyServiceClass。您的新类应该扩展 MyServiceClass,然后您可以覆盖 myMethod2() 并提供不同的“仅测试”实现。

    选项 2

    可以使用Mockito to Spy the class under test,但这是一种相当不正统的方法。

    如果你有控制权,我仍然建议重构代码

    【讨论】:

    • 为什么我们不能那样做..?
    • 因为您必须在测试中实例化 new MyServiceClass() 以便执行“真实”代码进行测试。因此,同一个类不能是模拟对象。
    • 是他们解决此问题的任何其他方法,而无需将方法移动到另一个类...?
    【解决方案2】:

    你尝试过元类吗?

    service.metaClass.myMethod2 = { return whatever }
    

    http://groovy.codehaus.org/JN3525-MetaClasses

    我滥用 metaClass 的次数可能超出了我的预期,但是当你想不出更好的做事方式时,这很好。

    【讨论】:

      【解决方案3】:

      有一个非常酷的技巧,您可以模拟服务的选定方法,同时保持服务的总体完整性,就像这样......

      def method1(){
          ...
         def result = method2(param)
         return result
      }
      
      
      def method2(Type param){
          ...
         return result
      }
      
      
      void "Test method1"() {
              given:
      
              def service = [
                      method2: {Type param -> [1,2,3,4]}
              ] as MyService
      
              when:
                  def result = service.method1()
      
              then:
                  result.count == 4
                  result == [1,2,3,4]
       }
      

      我的意思是,您可以通过定义一个包含方法名称作为键的映射和一个包含参数和模拟值作为值的闭包来模拟服务的方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-22
        • 1970-01-01
        • 2015-12-15
        • 2015-10-21
        • 1970-01-01
        相关资源
        最近更新 更多