【问题标题】:Junit for Spring Cache Manager用于 Spring 缓存管理器的 Junit
【发布时间】:2016-09-13 17:11:04
【问题描述】:

我在我的应用程序中使用弹簧缓存层,在编写单元测试以使用 Mockito 测试弹簧缓存层时遇到了问题。

请参考以下代码解决我的问题:

服务层:

    public CustomerServiceImpl implements CustomerService {
    @Autowired
    private CacheManager cacheManager;

    @Autowired
    private CustomerRepository customerRepository;//Repository is simple JPA repository interface which contains findByCustomerName()

    @Override
    @CachePut(value = "#customer", key = "#customer.customerName")
    public Customer insertOrUpdate(Customer customer) {
        return customerRepository.save(customer);
    }

    @Cacheable(value="customersCache", key = "#customerName")
    public Customer findByCustomerName(String customerName) {
        Customer customer = customerRepository.findByCustomerName(customerName);
        return customer;
    }
}

Service 层的 JUnit 测试代码:

@RunWith(PowerMockRunner.class)
@PrepareForTest(CustomerServiceImplTest.class)
public class CustomerServiceImplTest {

    @Spy
    CacheManager cacheManager = new ConcurrentMapCacheManager("customersCache");

    @Mock
    CustomerRepository CustomerRepository;

    @InjectMocks
    CustomerServiceImpl customerServiceImpl = new CustomerServiceImpl();

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testCacheForFindByCustomerName() {
        Customer customer1 = new Customer();
        customer1.setId("1");
        customer1.setName("John");
        Customer customer2 = new Customer();
        customer2.setId("2");
        customer2.setName("Sara");

        //this should save to cache   
        Mockito.when(CustomerRepository.save(customer1))
        .thenReturn(customer1);
        customerServiceImpl.insertOrUpdate(customer1);

        //Now it should retreive from cache, but not able to
      Mockito.when(CustomerRepository.findByCustomerName(Mockito.any(String.class)))
                .thenReturn(customer1, customer2);

        Customer result = customerServiceImpl.findByCustomerName("John");
        assertThat(result, is(customer1));

        result = customerServiceImpl.findByCustomerName("John");
        assertThat(result, is(customer1));
    }
}

例外:

我得到一个“java.lang.AssertionError:”,因为缓存层不起作用,并且调用已传递给存储库对象(两次),该对象返回了上面的“customer2”模拟对象,即存储库方法已被调用两次通过服务层获取相同的密钥。

另外,请注意我正在使用“Mockito”框架进行测试。

我曾尝试在 google 上搜索有关 spring 缓存的单元测试,并参考了以下 URL,它几乎使用了相同的概念,但它不适用于我上面的代码。

How to test Spring's declarative caching support on Spring Data repositories?

您能帮忙解决上述异常吗?

【问题讨论】:

    标签: java spring junit mockito spring-cache


    【解决方案1】:

    Spring Cache Manager 依赖于 Spring 管理应用程序。你不能用PowerMockRunner 得到它,你需要使用SpringJUnit4Runner。您仍然可以通过编程方式使用 PowerMock 或 Mockito,但不能作为 Runner。

    通常,您会将单元测试转变为 Spring 风格的集成测试,如下所示:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration
    public class SpringTest {
    
        @Configuration
        @EnableCaching
        static class SpringConfig{
            @Bean
            public CustomerService customerService(){
                return new CustomerServiceImpl(customerRepository());
            }
            @Bean
            public CustomerRepository customerRepository(){
                return Mockito.mock(CustomerRepository.class);
            }
        }
    
        @Autowired
        CustomerService customerService; // this will contain a proper managed cache
    
        @Autowired
        CustomerRepository customerRepository; // this is a mockito mock you can fine-tune
    }
    

    【讨论】:

    • 感谢您的帮助。我正在努力使用 Mockito 让它工作。
    • 感谢帮助
    猜你喜欢
    • 1970-01-01
    • 2016-05-05
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 2018-11-29
    • 2016-02-02
    • 2020-05-22
    • 1970-01-01
    相关资源
    最近更新 更多