@Cacheable 测试方法
我在课堂内有一个@cach的方法。 我尝试在第一次呼叫该方法后创建该缓存,然后,第二个调用不应进入方法 getcacheleads 。
@Service
public class LeadService {
@Autowired
private LeadRepository leadRepository;
@Autowired
public LeadService(LeadRepository leadRepository) {
this.leadRepository = leadRepository;
}
public void calculateLead(Lead leadBean) {
Lead lead = this.getCacheLeads(leadBean);
}
@Cacheable(cacheNames="leads", key="#leadBean.leadId")
public Lead getCacheLeads(Lead leadBean){
Lead result = leadRepository.findByLeadId(leadBean.getLeadId());
***logic to transform de Lead object***
return result;
}
}
但是,在测试中,从未使用过缓存,将其称为两次使用相同的参数( serviceSiscalled ),以确保将其调用两次以检查它。
@ExtendWith(SpringExtension.class)
public class LeadServiceTest {
private LeadService leadService;
@Mock
private LeadRepository leadRepository;
@Autowired
CacheManager cacheManager;
@BeforeEach
public void setUp(){
leadService = new LeadService(leadRepository);
}
@Configuration
@EnableCaching
static class Config {
@Bean
CacheManager cacheManager() {
return new ConcurrentMapCacheManager("leads");
}
}
@Test
public void testLead(){
givenData();
serviceIsCalled();
serviceIsCalled();
checkDataArray();
}
private void givenData() {
Lead lead = new Lead();
lead.setLeadId("DC635EA19A39EA128764BB99052E5D1A9A");
Mockito.when(leadRepository.findByLeadId(any()))
.thenReturn(lead);
}
private void serviceIsCalled(){
Lead lead = new Lead();
lead.setLeadId("DC635EA19A39EA128764BB99052E5D1A9A");
leadService.calculateLead(lead);
}
private void checkDataArray(){
verify(leadRepository, times(1)).findByLeadId(anyString());
}
}
为什么叫2次?
I have a @Cacheable method inside a class.
I try to create that cache after a first call to that method, then, the second call should't go inside the method getCacheLeads.
@Service
public class LeadService {
@Autowired
private LeadRepository leadRepository;
@Autowired
public LeadService(LeadRepository leadRepository) {
this.leadRepository = leadRepository;
}
public void calculateLead(Lead leadBean) {
Lead lead = this.getCacheLeads(leadBean);
}
@Cacheable(cacheNames="leads", key="#leadBean.leadId")
public Lead getCacheLeads(Lead leadBean){
Lead result = leadRepository.findByLeadId(leadBean.getLeadId());
***logic to transform de Lead object***
return result;
}
}
But during testing that cache is never used, calling it twice with same parameter (serviceIsCalled) to ensure it is called twice to check it.
@ExtendWith(SpringExtension.class)
public class LeadServiceTest {
private LeadService leadService;
@Mock
private LeadRepository leadRepository;
@Autowired
CacheManager cacheManager;
@BeforeEach
public void setUp(){
leadService = new LeadService(leadRepository);
}
@Configuration
@EnableCaching
static class Config {
@Bean
CacheManager cacheManager() {
return new ConcurrentMapCacheManager("leads");
}
}
@Test
public void testLead(){
givenData();
serviceIsCalled();
serviceIsCalled();
checkDataArray();
}
private void givenData() {
Lead lead = new Lead();
lead.setLeadId("DC635EA19A39EA128764BB99052E5D1A9A");
Mockito.when(leadRepository.findByLeadId(any()))
.thenReturn(lead);
}
private void serviceIsCalled(){
Lead lead = new Lead();
lead.setLeadId("DC635EA19A39EA128764BB99052E5D1A9A");
leadService.calculateLead(lead);
}
private void checkDataArray(){
verify(leadRepository, times(1)).findByLeadId(anyString());
}
}
Why is it called 2 times?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里发生了很多事情,有人看到这个并回答你的问题肯定需要阅读字里行间的内容。
首先,您的 Spring 配置甚至不正确。您使用 ConcurrentMapCacheManager “静态”声明 Spring 应用程序(和测试)使用的所有缓存的名称 构造函数接受缓存名称数组作为参数。
在这种情况下,您的第一个也是唯一的缓存称为“LEAD_DATA”。
但是,然后,在您的
@Service
LeadService
类中,@Cacheable
getCacheLeads(:Lead)
方法中,您声明缓存用作“线索”。这种未命中配置实际上会导致运行时出现类似于以下内容的异常:
此外,我没有看到
LeadsService
bean 调用@Cacheable
的“外部”任何内容,getCacheLeads(..)
方法。在您的测试中,您正在调用:如下所示:
如果
calculateLead(:Lead)
LeadService
方法正在调用@Cacheable
,getCacheLeads(:Lead)
LeadService
方法(内部),那么这不会导致缓存功能启动,因为您已经在 Spring 设置的 AOP 代理“后面”为您的LeadService
bean“启用”缓存行为。请参阅 Spring 框架 AOP 文档。
在您的情况下,这意味着:
但是,在
LeadSevice.calculateLead(:Lead)
和LeadService.getCacheLeads(:Lead)
之间,不涉及代理,因此 Spring 的缓存行为不会被应用。仅...
将导致用被调用的缓存拦截器装饰的 AOP 代理并应用缓存行为。
您可以看到,如果正确配置和使用,您的用例将正常工作,如我的 示例测试类,以您的域为模型。
查找解释为什么您的配置在您的情况下会失败的注释。
You have a lot of things going on here, and someone looking at this and answering your question would definitely have to read between the lines.
First, your Spring configuration is not even correct. You are declaring the names of all the caches used by your Spring application (and tests) "statically" with the use of the
ConcurrentMapCacheManager
constructor accepting an array of cache names as the argument.In this case, your 1 and only cache is called "LEAD_DATA".
But then, in your
@Service
LeadService
class,@Cacheable
getCacheLeads(:Lead)
method, you declare the cache to use as "leads".This miss configuration will actually lead to an Exception at runtime similar to the following:
Additionally, I don't see anything "outside" of the
LeadsService
bean calling the@Cacheable
,getCacheLeads(..)
method. Inside your test, you are calling:As follows:
If the
calculateLead(:Lead)
LeadService
method is calling the@Cacheable
,getCacheLeads(:Lead)
LeadService
method (internally), then that is not going to cause the caching functionality to kick in since you are already "behind" the AOP Proxy setup by Spring to "enable" caching behavior for yourLeadService
bean.See the Spring Framework AOP documentation on this matter.
In your case this means:
However, between
LeadSevice.calculateLead(:Lead)
andLeadService.getCacheLeads(:Lead)
, NO PROXY is involved, therefore Spring's caching behavior will not be applied.Only...
Will result in the AOP Proxy decorated with the Caching Interceptors being invoked and the caching behavior applied.
You can see that your use case will work correctly when configured and used correctly as demonstrated in my example test class, modeled after your domain.
Look for the comments that explain why your configuration will fail in your case.