java - 用于 Spring 缓存管理器的 Junit

标签 java spring junit mockito spring-cache

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

请引用以下代码解决我的问题:

服务层:

    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;
    }
}

服务层的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”模拟对象上面即通过服务层为同一个 key 调用存储库方法两次。

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

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

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

能否请您帮忙解决上述异常?

最佳答案

Spring 缓存管理器依赖于 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
}

关于java - 用于 Spring 缓存管理器的 Junit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39475533/

相关文章:

java - 测量完成各个流步骤的时间?

java - 尝试将 OneLogin OIDC 与 SpringBoot 结合使用时出错(错误 : redirect_uri_mismatch)

hibernate - init 方法调用失败;嵌套异常是 java.lang.IncompatibleClassChangeError : Implementing class

java - 如何在嵌套的 Junit 5 测试中访问外部测试实例/参数

java - JUnit/Mockito : throwing an exception in a new thread

java - Log4j2 模拟附加程序

java - Glassfish 密码别名

java - 简单的 Hello World servlet 在 Eclipse Tomcat 中给出错误 404

java - 按浮点值对 2D Java 数组进行排序

java - AspectJ 的 CGLIB 字节代码生成