Java Mockito无法创建@Autowired Spring数据存储库的Spy

Java Mockito无法创建@Autowired Spring数据存储库的Spy,java,unit-testing,spring-boot,spring-data-jpa,spy,Java,Unit Testing,Spring Boot,Spring Data Jpa,Spy,我正试图用Mockito.spy功能覆盖我的整个测试环境,所以只要我想,我就可以存根一个方法,但所有其他调用都会转到默认功能。 这在服务层上运行得非常好,但我在存储库层上遇到了问题 我的设置如下: Mockito-2.15.0 弹簧-5.0.8 SpringBoot-2.0.4 存储库: public interface ARepository extends CrudRepository<ADBO, Long> {} 我的测试班: @ActiveProfiles("enableS

我正试图用Mockito.spy功能覆盖我的整个测试环境,所以只要我想,我就可以存根一个方法,但所有其他调用都会转到默认功能。 这在服务层上运行得非常好,但我在存储库层上遇到了问题

我的设置如下:

Mockito-2.15.0 弹簧-5.0.8 SpringBoot-2.0.4

存储库:

public interface ARepository extends CrudRepository<ADBO, Long> {}
我的测试班:

@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());

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

  • 假定既不是嘲笑也不是间谍:
    org.mockito.exceptions.misusing.NotAMockException:
    传递给when()的参数不是模拟!
    更正的示例…
  • 假设是一个模拟,但不是间谍(这是我得到的结果):
    result(1):ADBO(id=null,testValue=null)
    结果全部:[]

  • 一个间谍(这就是我想要的):
    result(1):ADBO(id=null,testValue=null)
    结果全部:[ADBO(id=1,testValue=bar)]

我将此行为归因于以下事实:存储库的spring实例化在后台更加复杂,并且在调用
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
,这让我觉得后台的对象没有正确实例化

最后我的问题:


如何使用@Autowired在UnitTest中获取Spring数据存储库的spy实例?

您应该使用
@SpyBean
,但不幸的是,它已损坏,无法用于Spring数据存储库

链接到问题:

为什么这么复杂?用
@SpyBean
注释要监视的字段,而不是试图将专用配置类固定到位。请参阅在存储库上使用
@SpyBean
而不是
@Autowire
会导致相同的行为,它会变成模拟而不是间谍。既然spring boot可以帮助您解决问题,为什么还要在存储库周围进行如此复杂的测试呢?此外,这需要您了解存储库的潜在复杂性及其工作原理。存在一个已打开的bug:它对外部客户端也不起作用。这是一个已知的问题吗?
@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());

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