Caching in Spring Mechanism
Simple Model
@Entity
public class Book {
@Id
private UUID id;
private String title;
}
repository interface that has a @Cacheable method
public interface BookRepository extends CrudRepository<Book, UUID> {
@Cacheable(value = "books", unless = "#a0=='Foundation'")
Optional<Book> findFirstByTitle(String title);
}
unless < 제외 조건 (필수는 아님)
#title " 대신 SpEL 표현식 "#a0" 에 유의할 것
프록시가 매개변수 이름을 유지하지 않기 때문에 #root.arg[0], p0 또는 a0 표기법을 사용함
Testing
The goal of our tests is to make sure the caching mechanism works. Therefore, we don't intend to cover the Spring Data repository implementation or the persistence aspects.
Spring Boot Test
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = CacheApplication.class)
public class BookRepositoryIntegrationTest {
@Autowired
CacheManager cacheManager;
@Autowired
BookRepository repository;
@BeforeEach
void setUp() {
repository.save(new Book(UUID.randomUUID(), "Dune"));
repository.save(new Book(UUID.randomUUID(), "Foundation"));
}
private Optional<Book> getCachedBook(String title) {
return ofNullable(cacheManager.getCache("books")).map(c -> c.get(title, Book.class));
}
Book 요청 후 Cache에 배치되는지 확인해본다
@Test
void givenBookThatShouldBeCached_whenFindByTitle_thenResultShouldBePutInCache() {
Optional<Book> dune = repository.findFirstByTitle("Dune");
assertEquals(dune, getCachedBook("Dune"));
}
that some books are not placed in the cache:
@Test
void givenBookThatShouldNotBeCached_whenFindByTitle_thenResultShouldNotBePutInCache() {
repository.findFirstByTitle("Foundation");
assertEquals(empty(), getCachedBook("Foundation"));
}
Spring에서 제공하는 CacheManager를 사용 하고 각 repository.findFirstByTitle 작업 후 CacheManager가 @Cacheable 규칙 에 따라 책을 포함하는지(또는 포함하지 않는지) 확인한다
Plain Spring
@Configuration that provides the mock implementation for our BookRepository:
@ContextConfiguration
@ExtendWith(SpringExtension.class)
public class BookRepositoryCachingIntegrationTest {
private static final Book DUNE = new Book(UUID.randomUUID(), "Dune");
private static final Book FOUNDATION = new Book(UUID.randomUUID(), "Foundation");
private BookRepository mock;
@Autowired
private BookRepository bookRepository;
@EnableCaching
@Configuration
public static class CachingTestConfig {
@Bean
public BookRepository bookRepositoryMockImplementation() {
return mock(BookRepository.class);
}
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("books");
}
}
BookRepository 는 a proxy around our mock. 이다, Mockito 유효성 검사를 위해 AopTestUtils.getTargetObject를통해 실제 모의를 검색한다
CachingTestConfig가 한 번만 로드되기 때문에 테스트 사이에 재설정(mock) 해야한다
@BeforeEach
void setUp() {
mock = AopTestUtils.getTargetObject(bookRepository);
reset(mock);
when(mock.findFirstByTitle(eq("Foundation")))
.thenReturn(of(FOUNDATION));
when(mock.findFirstByTitle(eq("Dune")))
.thenReturn(of(DUNE))
.thenThrow(new RuntimeException("Book should be cached!"));
}
after a book is placed in the cache, there are no more interactions with the repository implementation when later trying to retrieve that book
책이 캐싱된 후 책을 검색할 때 repository 를 사용하는지 테스트 한다
@Test
void givenCachedBook_whenFindByTitle_thenRepositoryShouldNotBeHit() {
assertEquals(of(DUNE), bookRepository.findFirstByTitle("Dune"));
verify(mock).findFirstByTitle("Dune");
assertEquals(of(DUNE), bookRepository.findFirstByTitle("Dune"));
assertEquals(of(DUNE), bookRepository.findFirstByTitle("Dune"));
verifyNoMoreInteractions(mock);
}
that for non-cached books, we invoke the repository every time:
캐싱이 없는 경우에는 repository를 계속 호출하는지 확인한다
@Test
void givenNotCachedBook_whenFindByTitle_thenRepositoryShouldBeHit() {
assertEquals(of(FOUNDATION), bookRepository.findFirstByTitle("Foundation"));
assertEquals(of(FOUNDATION), bookRepository.findFirstByTitle("Foundation"));
assertEquals(of(FOUNDATION), bookRepository.findFirstByTitle("Foundation"));
verify(mock, times(3)).findFirstByTitle("Foundation");
}
'Web > spring' 카테고리의 다른 글
[Spring] Assertions in JUnit 4 and JUnit 5 (0) | 2023.04.25 |
---|---|
[Spring] A Spring Custom Annotation for a Better DAO (0) | 2023.04.24 |
[Spring Test] (0) | 2023.04.22 |
[JPA Repository] supported keyword (0) | 2023.04.20 |
[Spring] stereotype (0) | 2023.04.15 |