Java Mockito接缝与Spring缓存不兼容

Java Mockito接缝与Spring缓存不兼容,java,spring,mockito,Java,Spring,Mockito,在尝试将Mockito与Spring缓存一起使用时,我遇到了意想不到的行为 Mockito不能很好地与Spring AOP配合使用。有谁能向我证实这是一个bug或者我做错了什么 在这段代码中,我们可以看到测试在尝试存根方法时将抛出SpelEvaluationException 您可以复制克隆此GitHub存储库的问题。在那里,您将找到包含所有依赖项的pom.xml @RunWith(SpringJUnit4ClassRunner.class) @上下文配置 公共类SpringCacheMock

在尝试将Mockito与Spring缓存一起使用时,我遇到了意想不到的行为

Mockito不能很好地与Spring AOP配合使用。有谁能向我证实这是一个bug或者我做错了什么

在这段代码中,我们可以看到测试在尝试存根方法时将抛出
SpelEvaluationException

您可以复制克隆此GitHub存储库的问题。在那里,您将找到包含所有依赖项的pom.xml

@RunWith(SpringJUnit4ClassRunner.class)
@上下文配置
公共类SpringCacheMockitoCompatibilityTest{
接口MyRepo扩展存储库{
//@可缓存(cacheNames=“sample”,key=“#key.id”)
@可缓存(cacheNames=“sample”,key=“new org.springframework.cache.interceptor.SimpleKey(#key.id)”)
对象findByEmail(MyKey);
}
@AllArgsConstructor
公共静态类MyKey{
长id;
字符串名;
@凌驾
公共布尔等于(对象obj){
返回id==((MyKey)obj.id;
}
}
@配置
@启用缓存
静态类配置{
@豆子
CacheManager CacheManager(){
返回新的ConcurrentMapCacheManager(“示例”);
}
@豆子
MyRepo MyRepo(){
返回Mockito.mock(MyRepo.class);
}
}
@自动连线缓存管理器;
@自动连线MyRepo回购;
@试验
当对象()使用任何匹配项时,通过SpeleValuationException_公共无效{
对象优先=新对象();
MyKey MyKey=新的MyKey(1l,“名称”);
//下面两行都将抛出SpelEvaluationException:EL1007E:在null上找不到属性或字段“id”
//doReturn(first.when(repo.findByEmail)(any(MyKey.class));
doReturn(first).when(repo.findByEmail(myKey);
objectresult1=repo.findByEmail(myKey);
验证(回购,次数(1))。findByEmail(myKey);
}
}

我认为您可能过度简化了示例。您只是在一个mock上断言,这是毫无意义的。我得到了最小的可重复性示例,但我无法确定这里的最终目标是什么。为什么要将
@Cacheble
添加到模拟?为什么测试
@Cacheable
?Spring已经做到了这一点。只是不确定想要的结果是什么以及为什么。Hy@DCTID,谢谢!为什么测试
@Cacheable
?我不想测试
@Cacheable
,我想测试使用Spring缓存的实现是否正常工作。我的实现比这个最小的可复制示例要复杂得多。但是我认为这个例子非常清楚地显示了在使用Mockito和Spring Cache时出现的一些意外行为。我试图重现这一点,但是当定义了mock行为时,我得到了一个不同的异常。看起来
@Cachable
AOP
-impl在这一点上会产生干扰,并导致整个过程失败。也许您可以添加正在使用的依赖项。但是我不知道为什么你想让mockito参与这个测试?我可以确认,我在Spring AOP和mockito Mocks的结合中也遇到了问题。因此,这种组合可能存在一个普遍的问题。请记住:AOP是一个重写字节码的框架。Mockito是一个动态生成字节码的框架。当它在第一时间起作用时,你应该感到高兴……我认为你可能过度简化了你的例子。您只是在一个mock上断言,这是毫无意义的。我得到了最小的可重复性示例,但我无法确定这里的最终目标是什么。为什么要将
@Cacheble
添加到模拟?为什么测试
@Cacheable
?Spring已经做到了这一点。只是不确定想要的结果是什么以及为什么。Hy@DCTID,谢谢!为什么测试
@Cacheable
?我不想测试
@Cacheable
,我想测试使用Spring缓存的实现是否正常工作。我的实现比这个最小的可复制示例要复杂得多。但是我认为这个例子非常清楚地显示了在使用Mockito和Spring Cache时出现的一些意外行为。我试图重现这一点,但是当定义了mock行为时,我得到了一个不同的异常。看起来
@Cachable
AOP
-impl在这一点上会产生干扰,并导致整个过程失败。也许您可以添加正在使用的依赖项。但是我不知道为什么你想让mockito参与这个测试?我可以确认,我在Spring AOP和mockito Mocks的结合中也遇到了问题。因此,这种组合可能存在一个普遍的问题。请记住:AOP是一个重写字节码的框架。Mockito是一个动态生成字节码的框架。当它在第一时间起作用时,要高兴。。。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class SpringCacheMockitoIncompatibilityTest {

    interface MyRepo extends Repository<Object, Long> {

        //@Cacheable(cacheNames = "sample", key="#key.id")
        @Cacheable(cacheNames = "sample", key = "new org.springframework.cache.interceptor.SimpleKey(#key.id)")
        Object findByEmail(MyKey key);
    }

    @AllArgsConstructor
    public static class MyKey{
        long id;
        String name;

        @Override
        public boolean equals(Object obj){
            return id == ((MyKey)obj).id;
        }
    }

    @Configuration
    @EnableCaching
    static class Config {

        @Bean
        CacheManager cacheManager() {
            return new ConcurrentMapCacheManager("sample");
        }

        @Bean
        MyRepo myRepo() {
            return Mockito.mock(MyRepo.class);
        }
    }

    @Autowired CacheManager manager;
    @Autowired MyRepo repo;

    @Test
    public void throwsSpelEvaluationException_whenAnyMatcherIsUsedWithObject() {

        Object first = new Object();

        MyKey myKey = new MyKey(1l,"name");

        //both lines below will throws SpelEvaluationException: EL1007E: Property or field 'id' cannot be found on null

        //doReturn(first).when(repo).findByEmail(any(MyKey.class));
        doReturn(first).when(repo).findByEmail(myKey);

        Object result1 = repo.findByEmail(myKey);

        verify(repo,times(1)).findByEmail(myKey);
    }
}