如何检查内部服务是否引发异常?

时间:2018-06-18 21:39:14

标签: java spring groovy spock

我正在尝试为新服务编写单元测试。该服务返回void并使用其他自动连线服务来完成一些工作。我想测试一个内部服务之一抛出一个由被测试的顶级服务捕获的异常的情况。如何在'then'子句中验证内部服务是否在被测试服务捕获时引发了异常?

我还要验证是否已调用静态方法来记录结果,但我也看不到使用Spock的方法。这些是该服务的唯一输出,因此我想验证它们是否正常工作。

1 个答案:

答案 0 :(得分:1)

要解决问题的第一部分:

假设我们具有以下结构:

interface ServiceUnderTest {
   void foo()
}
interface InternalService {
   int bar() throws IllegalArgumentException
}

class ServiceUnderTestImpl implements ServiceUnderTest {
    InternalService internalService
    ServiceUnderTestImpl(InternalService internalService) {
       this.internalService = internalService
    }

    void foo() {
        try {
          internalService.bar()
        } catch(IllegalArgumentException ex) {
          println "Got you"
        }
    }
 }

您正在foo()中测试方法ServiceUnderTest,它将返回void

因此,我建议创建内部服务存根,该存根在调用其bar方法时会引发异常

该测试将检查调用foo时是否引发了异常(这意味着内部服务引发的异常已被捕获并正确处理)

测试看起来像这样:

class SampleSpockTest extends Specification {
   def "test sample" () {
      given:
        def internalService = Stub(InternalService)
        def subject = new ServiceUnderTestImpl(internalService)
        internalService.bar() >> {throw new IllegalArgumentException("Sample 
           exception")}
      when:
        subject.foo()
      then:
        noExceptionThrown()
     }
 }

我认为您不应该像您所说的那样“签入“内部服务引发异常的子句”,实际上是在检查ServiceUnderTest。返回void并不是最佳选择,因为您可能无法真正知道它的作用,可能是通过在调用foo方法或其他方法后检查其内部状态来实现的,但是至少可以检查内部服务是否已处理了异常调用并抛出异常。

关于静态方法模拟,您可能不应该这样做,因为模拟不能很好地与静态调用配合使用。您可以使用PowerMock或PowerMockito之类的“特殊”工具,但我相信,它们指向的是代码味道,应主要用于遗留代码。不过,这只是我的意见。