如何在Groovy Spock中模拟Autowired构造函数依赖项

问题描述

我有一个正在为其编写常规测试用例的类。此类具有构造函数自动装配,并调用一个方法来初始化字段。

@Service
public class ServiceA {

private final PrincipalDao principalDao;
    @Autowired
    public ServiceA(final PrincipalDao principalDao){
        this.principalDao=principalDao;
        this.serviceMap = getMap();           
    }
            
    private Map<> getMap() {
        final List<ClassA> classAList = principalDao.findAll(); //this line returns null
       
    }       
}
    

此行final List<ClassA> classAList = principalDao.findAll();返回null,我无法像下面这样以常规方式对其进行模拟:

principalDao.findAll() >> list

因为它甚至在常规测试用例中在我的上述行被调用之前就被调用

解决方法

在没有看到您进行单元测试的情况下,很难说出问题是什么,但是有时我遇到的一个普遍误解是模拟的时机。

这是一个示例代码,详细说明了我的意思。由于您的问题中缺少部分代码,因此请假设其中的某些部分,但是我确定它可以解释我的观点,并希望能帮助您找到答案:

服务类别:

@Service
public class ServiceA{

  private final PrincipalDao principalDao;
  private final Map<String,String> serviceMap;

  @Autowired
  public ServiceA(final PrincipalDao principalDao){
    this.principalDao = principalDao;
    this.serviceMap = getMap();
  }

  private Map<String,String> getMap(){
    final HashMap<String,String> stringStringHashMap = new HashMap<String,String>();
    stringStringHashMap.put("hello",principalDao.khello());
    return stringStringHashMap;
  }

  public String printServiceMap() {
    return serviceMap.get("hello");
  }
}
class ServiceATest extends Specification {

  def "some test"() {
    given:
    PrincipalDao principalDao = Mock()
    principalDao.khello() >> "khello" // this is the key here. Mocking is happening before instantiation of ServiceA
    ServiceA someService = new ServiceA(principalDao)

    expect:
    "khello" == someService.printServiceMap()
  }
}

此单元测试成功通过。这里的重点是嘲弄的时间。 principalDao.khello() >> "khello"发生在new ServiceA(principalDao)之前。

如果您不需要修改每个单元测试的serviceMap,也可以执行此操作,因此您不必为每个单元测试定义它:

class ServiceATest extends Specification {

  @Shared
  PrincipalDao principalDao = Mock()
  ServiceA someService = new ServiceA(principalDao)

  def setupSpec() {
    principalDao.khello() >> "khello"
  }

  def "some test"() {
    expect:
    "khello" == someService.printServiceMap()
  }
}