Spock 如何在方法中模拟 Autowired class' 函数调用

Spock How to mock Autowired class' function call within a method

我有一个 class 我想测试它看起来像这样: 包裹 com.something;

import org.springframework.beans.factory.annotation.Autowired;
public class ClassToTest implements InterfaceToTest{

  @Autowired
  AnotherService serviceA;

  @Override
  public List<String> methodToTest(List<String> randomVar){
    ...
    String stringA = serviceA.someFunction(randomVar);
    ...
  }
}

在使用 spock 进行测试时,如何将调用 serviceA.someFunction(randomVar) 的结果模拟为 return 我选择的任何字符串?

package com.something;
import spock.lang.Shared
import spock.lang.Specification
class TestClass extends Specification{
  @Shared InterfaceToTest classToTest = new ClassToTest()

  static doWithSpring = {
    serviceA(AnotherService)
  }

  def "tests-part-1"(){
    when: "something"
    ...
    then: "expect this"
    ...
  }
}

我不知道从这里到哪里去。我的 IDE 显示我添加到测试 class 的 doWithSpring 代码有错误。关于如何处理这个问题有什么想法吗?

我建议更多地从单元测试的角度来考虑它。你想模拟 spring 框架的东西,只是确保你正在测试你的逻辑。这对 Spock 来说很容易做到。

ClassToTest myClass = new ClassToTest(serviceA: Mock(AnotherService))

def "test my method"() {
  when:
  myClass.methodToTest([])

  then:
  1 * myClass.serviceA.someFunction([]) >> 'A string'
}

从这里,您可以查看驱动它的数据或使用 >>> 并将您想要的不同字符串列表传递给 return。

如果您正在进行单元测试,请按照@rockympls 的建议进行操作。

如果您正在 integration/component 测试,则包含 spock-spring 依赖项并查看来自 Spock 人员的 test examples。此外,如果您使用 Spring Boot 1.4+,您可以执行以下操作:

@SpringBootTest(classes = Application)
@ContextConfiguration
class SomeIntegrationTest extends Specification {

    @Autowired
    SomeService someService

    def 'some test case'() {
        ...
    }
}

有关 Spring 引导测试内容的更多信息,请参阅 this

启用单元测试的一个简单解决方案是更改 ClassToTest 以具有一个构造函数来设置 serviceA 字段,如下所示:

import org.springframework.beans.factory.annotation.Autowired;
public class ClassToTest implements InterfaceToTest{

private AnotherService serviceA;

@Autowired
public ClassToTest(final AnotherService serviceA){
   this.serviceA = serviceA;
}

@Override
public List<String> methodToTest(List<String> randomVar){
...
String stringA = serviceA.someFunction(randomVar);
...
}
}

然后在您的 spock 单元测试中,您可以在构造函数中提供一个模拟:

class TestClass extends Specification{
 def mockServiceA = Mock(AnotherService)
 @Shared InterfaceToTest classToTest = new ClassToTest(mockServiceA)

并且在每个测试用例中,您可以使用通常的 spock 方式进行模拟:

1 * mockServiceA.someFunction(_) >> 'A string'