【问题标题】:Unit test for method retrieving data from CacheManger using for loop使用 for 循环从 CacheManger 检索数据的方法的单元测试
【发布时间】:2019-03-18 04:11:45
【问题描述】:

我有一个方法可以从下一个 webapi 检索人员并存储在缓存中,我想从缓存管理器中获取相同的缓存数据。我很难为这种方法编写单元测试。 任何帮助都非常感谢

import javax.cache.Cache;
import javax.cache.CacheManager;

@Autowired
@Qualifier(value = "cacheManager")
private CacheManager cacheManager;

*public List<Person> fallbackPersons() {
      List<Person> data = new ArrayList<>();
    for (Cache.Entry<Object, Object> entry :cacheManager.getCache("person"){ 
        data = (List<Person>) entry.getValue();
        }
    return data;
}*

【问题讨论】:

    标签: java spring-boot junit ehcache


    【解决方案1】:

    您可以模拟 CacheManager,将其存根并验证结果如下:

        @RunWith(MockitoJUnitRunner.class)
        public class PersonsServiceTest {
    
            @Mock
            private CacheManager cacheManager;
    
            @InjectMocks
            PersonsService service = new PersonsService();
    
            @Before
            public void setup() {
                 MockitoAnnotations.initMocks(this);
            }
    
            @Test
            public void fallbackPersonsWithNonEmptyCache() {
                List<Person> persons = Collections.singletonList(new Person());  // create person object as your Person class definition
                // mock cache entry
                Cache.Entry <Object, Object> entry = Mockito.mock(Cache.Entry.class);
    
                // do stubbing
                Mockito.when(entry.getValue()).thenReturn(persons);
                Mockito.when(cacheManager.getCache(Matchers.anyString()))
                        .thenReturn(entry);
    
                // execute
                List<Person> persons = service.fallbackPersons();
    
                // verify
                Assert.assertNotNull(persons);
                Assert.assertFalse(persons.isEmpty());
            }
        }
    

    【讨论】:

    • 感谢您的回复。下面的行应该返回缓存而不是emptyList Mockito.when(cacheManager.getCache(Matchers.anyString())) .thenReturn(Collections.emptyList());此外,我仍然从 (Cache.Entry entry :cacheManager.getCache("person"){ 行获取 NullPointerExcetpion
    • @suraz 我已经更新了示例,请看一下!
    • 我检查了你更新的示例@yogen,但我得到了同样的 NullPointerException 错误。
    • @suraz 在执行前断言或调试如果cacheManager 已被模拟.. 还要确保你有@RunWith(MockitoRunner.class) 因为这表明启用模拟注释.. 如果仍然遇到相同的错误,告诉我我给你的代码和你有的不同。
    • 感谢您的快速响应。它帮助我找出解决方案。实际上,我必须模拟每一步才能通过测试。下面我已经发布了解决方案,希望它可能有人。
    【解决方案2】:

    1.单元测试

    如果您打算通过模拟 CacheManager 对公共方法 fallbackPersons 进行单元测试,我强烈建议您更改注入 cacheManager bean 的样式,使用构造函数注入:

    import javax.cache.Cache;
    import javax.cache.CacheManager;
    
    @Service    
    public class PersonsService {
        private final CacheManager cacheManager;
    
        @Autowired
        public PersonsService(@Qualifier(value = "cacheManager") CacheManager cacheManager) {
            this.cacheManager = cacheManager;
        }
    
        public List<Person> fallbackPersons() {
            List<Person> data = new ArrayList<>();
            for (Cache.Entry<Object, Object> entry : cacheManager.getCache("person")) { 
                data = (List<Person>) entry.getValue();
            }
    
            return data;
        }
    }
    

    这个类现在很容易通过注入 CacheManager 的模拟和编程它的行为来进行单元测试,你不需要引导 Spring 上下文(应用 @Autowired),或者使用 Powermock 库来访问私有属性。

    单元测试示例:

    public class PersonsServiceTest {
        @Test
        public void fallbackPersonsWithEmptyCache() {
            CacheManager cacheManager = Mockito.mock(CacheManager.class);
            Mockito.when(cacheManager.getCache(Matchers.anyString()))
                .thenReturn(Collections.emptyList());
    
            PersonsService service = new PersonsService(cacheManager);
            List<Person> persons = service.fallbackPersons();
            Assert.assertNotNull(persons);
            Assert.assertTrue(persons.isEmpty());
        }
    }
    

    2。集成测试

    如果您真的想使用 Spring 的真实缓存管理器实现来测试您的服务,那么您应该查看有关如何使用 Spring Framework 提供的 AbstractJUnit4SpringContextTestsAbstractTestNGSpringContextTests 类的示例。它们将允许您初始化真正的 Spring 上下文并注入真正的 CacheManager 实现,例如 EhCahce 等。

    【讨论】:

    • 感谢您的回复。下面的行应该返回缓存而不是emptyList Mockito.when(cacheManager.getCache(Matchers.anyString())) .thenReturn(Collections.emptyList());此外,我仍然从 (Cache.Entry entry :cacheManager.getCache("person"){ 行获取 NullPointerExcetpion
    【解决方案3】:

    我的问题的正确解决方案。

    @ActiveProfiles("test")
    @RunWith(MockitoJUnitRunner.class)
    @Slf4j
    public class CacheTest {
    
        @Spy
        @InjectMocks
        PersonService personService;
    
        @Mock
        private CacheManager cacheManager;
    
        @Before
        public void setup() {
            MockitoAnnotations.initMocks(this);
        }
    
        @Test
        public void fallbackMCCsWithNonEmptyCache() {
    
            List<Person> persons = Collections.singletonList(new Person());
    
            Iterator<Cache.Entry <Object, Object>> cacheIterator = 
            Mockito.mock(Iterator.class);
            Cache <Object, Object> cache = Mockito.mock(Cache.class);
            Cache.Entry <Object, Object> entry = Mockito.mock(Cache.Entry.class);
            Mockito.when(cacheManager.getCache(Mockito.anyString()))
            .thenReturn(cache);
            Mockito.when(cache.iterator()).thenReturn(cacheIterator);
            List<Person> personList = personService.fallbackPersons();
            Assert.assertNotNull(personList);
            Assert.assertTrue(personList.isEmpty());
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-02
      相关资源
      最近更新 更多