Mockito无法创建Spring-Data Repository@Autowired间谍

我正在尝试用Mockito.spy功能覆盖我的整个测试环境,所以每当我想要时,我都可以存根一个方法,但所有其他调用都转到默认功能。这在服务层中效果很好,但我在存储库层上遇到了问题。

我的设置如下:

Mockito - 2.15.0 春季 - 5.0.8 春季靴 - 2.0.4

存储 库:

public interface ARepository extends CrudRepository<ADBO, Long> {}

服务:

@Service
public class AService {

    @Autowired
    ARepository aRepository;

    public ADBO getById(long id) {
        return aRepository.findById(id).orElse(null);
    }

    public Iterable<ADBO> getAll() {
        return aRepository.findAll();
    }
}

间谍的配置:

@Profile("enableSpy")
@Configuration
public class SpyConfig {

    @Bean
    @Primary
    public ARepository aRepository() {
        return Mockito.spy(ARepository.class);
    }
}

还有我的测试课:

@ActiveProfiles("enableSpy")
@RunWith(SpringRunner.class)
@SpringBootTest
public class AServiceTest {

    @Autowired
    AService aService;

    @Autowired
    ARepository aRepository;

    @Test
    public void test() {
        ADBO foo = new ADBO();
        foo.setTestValue("bar");
        aRepository.save(foo);

        doReturn(Optional.of(new ADBO())).when(aRepository).findById(1L);
        System.out.println("result (1):" + aService.getById(1));

        System.out.println("result all:" + aService.getAll());

    }
}

现在,此测试有三种可能的结果:

  • a存储库既不是模拟也不是间谍:
    org.mockito.exceptions.misusing.NotAMockException: Argument passed to when() is not a mock! Example of corr...
  • aRepository是一个模拟,但不是间谍(这是我得到的结果):
    result (1):ADBO(id=null, testValue=null) result all:[]

  • a存储库是间谍(这是我想要的):
    result (1):ADBO(id=null, testValue=null) result all:[ADBO(id=1, testValue=bar)]

我将此行为归因于这样一个事实,即存储库的春季实例化在后台更加复杂,并且在调用 时未正确实例化存储库。Mockito.spy(ARepository.class)

我还尝试将正确的实例自动连接到配置中,并使用@Autowired对象进行调用。Mockito.spy()

这导致:

Cannot mock/spy class com.sun.proxy.$Proxy75
Mockito cannot mock/spy because :
 - final class

根据我的研究,Mockito可以从v2.0.0开始模拟和监视最终类。

调用返回,这导致我认为后台中的对象未正确实例化。Mockito.mockingDetails(aRepository).isSpy()true

最后我的问题:

如何在我的UnitTest中获取Spring-Data Repository的间谍实例,@Autowired?


答案 1

应使用 @SpyBean 中的 。spring-boot-test

这曾经被打破(根据Spring Boot问题#7033),但现在已经修复并自Spring Boot以来得到了支持。2.5.3

如果您仍然收到此错误并且无法更新Spring Boot版本,则可能需要尝试@Mateusz Zając在回答此问题时提出的解决方法。


答案 2

@SpyBean现在与 spring 数据存储库起使用,因为 spring boot 版本 2.5.3

如果无法升级,可以通过在测试方法主体中实例化间谍来解决此问题:

var yourSpy = Mockito.mock(FooRepository.class, AdditionalAnswers.delegatesTo(real))

推荐