From 536008dff3d5f77db90ad5bb4bd259287f9a6b1b Mon Sep 17 00:00:00 2001 From: Adrian Maghear Date: Thu, 4 Jun 2020 16:29:55 +0200 Subject: [PATCH 1/4] [BAEL-3841] declarative caching testing --- spring-caching/pom.xml | 14 +++ .../springdatacaching/model/Book.java | 21 +++++ .../repositories/BookRepository.java | 15 ++++ spring-caching/src/main/resources/data.sql | 7 -- spring-caching/src/main/resources/schema.sql | 19 ---- .../BookRepositoryCachingIntegrationTest.java | 86 +++++++++++++++++++ .../BookRepositoryIntegrationTest.java | 58 +++++++++++++ 7 files changed, 194 insertions(+), 26 deletions(-) create mode 100644 spring-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java create mode 100644 spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java delete mode 100644 spring-caching/src/main/resources/data.sql delete mode 100644 spring-caching/src/main/resources/schema.sql create mode 100644 spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java create mode 100644 spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java diff --git a/spring-caching/pom.xml b/spring-caching/pom.xml index 80644f8a5f..5a320d3048 100644 --- a/spring-caching/pom.xml +++ b/spring-caching/pom.xml @@ -58,6 +58,20 @@ org.springframework.boot spring-boot-starter-jdbc + + org.projectlombok + lombok + 1.18.12 + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.data + spring-data-commons + 2.3.0.RELEASE + 3.5.2 diff --git a/spring-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java b/spring-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java new file mode 100644 index 0000000000..7de567f0db --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/springdatacaching/model/Book.java @@ -0,0 +1,21 @@ +package com.baeldung.springdatacaching.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import java.util.UUID; + +@Data +@Entity +@NoArgsConstructor +@AllArgsConstructor +public class Book { + + @Id + private UUID id; + private String title; + +} diff --git a/spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java b/spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java new file mode 100644 index 0000000000..d7f80b8b57 --- /dev/null +++ b/spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java @@ -0,0 +1,15 @@ +package com.baeldung.springdatacaching.repositories; + +import com.baeldung.springdatacaching.model.Book; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.repository.CrudRepository; + +import java.util.Optional; +import java.util.UUID; + +public interface BookRepository extends CrudRepository { + + @Cacheable(value = "books", unless="#a0=='Foundation'") + Optional findFirstByTitle(String title); + +} diff --git a/spring-caching/src/main/resources/data.sql b/spring-caching/src/main/resources/data.sql deleted file mode 100644 index e4165ae71f..0000000000 --- a/spring-caching/src/main/resources/data.sql +++ /dev/null @@ -1,7 +0,0 @@ -INSERT INTO CUSTOMER VALUES(1001,'BAELDUNG'); - -INSERT INTO ITEM VALUES(10001,'ITEM1',50.0); -INSERT INTO ITEM VALUES(10002,'ITEM2',100.0); - -INSERT INTO ORDERDETAIL VALUES(300001,1001,10001,2); -INSERT INTO ORDERDETAIL VALUES(300002,1001,10002,5); \ No newline at end of file diff --git a/spring-caching/src/main/resources/schema.sql b/spring-caching/src/main/resources/schema.sql deleted file mode 100644 index 5862499bc0..0000000000 --- a/spring-caching/src/main/resources/schema.sql +++ /dev/null @@ -1,19 +0,0 @@ -CREATE TABLE CUSTOMER( - CUSTOMERID INT PRIMARY KEY, - CUSTOMERNAME VARCHAR(250) NOT NULL -); - -CREATE TABLE ITEM( -ITEMID INT PRIMARY KEY, -ITEMDESC VARCHAR(250), -PRICE DOUBLE -); - -CREATE TABLE ORDERDETAIL( -ORDERID INT PRIMARY KEY, -CUSTOMERID INT NOT NULL, -ITEMID INT NOT NULL, -QUANTITY INT, -FOREIGN KEY (customerid) references CUSTOMER(customerid), -FOREIGN KEY (itemid) references ITEM(itemid) -); \ No newline at end of file diff --git a/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java b/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java new file mode 100644 index 0000000000..49ecc3a058 --- /dev/null +++ b/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java @@ -0,0 +1,86 @@ +package com.baeldung.springdatacaching.repositories; + +import com.baeldung.springdatacaching.model.Book; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.util.AopTestUtils; + +import java.util.UUID; + +import static java.util.Optional.of; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +@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"); + } + + } + + @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!")); + } + + @Test + void givenCachedBookWhenFindByTitleThenRepositoryShouldNotBeHit() { + assertEquals(of(DUNE), bookRepository.findFirstByTitle("Dune")); + verify(mock).findFirstByTitle("Dune"); + + assertEquals(of(DUNE), bookRepository.findFirstByTitle("Dune")); + assertEquals(of(DUNE), bookRepository.findFirstByTitle("Dune")); + + verifyNoMoreInteractions(mock); + } + + @Test + void givenNotCachedBookWhenFindByTitleThenRepositoryShouldBeHit() { + assertEquals(of(FOUNDATION), bookRepository.findFirstByTitle("Foundation")); + assertEquals(of(FOUNDATION), bookRepository.findFirstByTitle("Foundation")); + assertEquals(of(FOUNDATION), bookRepository.findFirstByTitle("Foundation")); + + verify(mock, times(3)).findFirstByTitle("Foundation"); + } + +} diff --git a/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java b/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java new file mode 100644 index 0000000000..56bc898bd0 --- /dev/null +++ b/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java @@ -0,0 +1,58 @@ +package com.baeldung.springdatacaching.repositories; + +import com.baeldung.caching.boot.CacheApplication; +import com.baeldung.springdatacaching.model.Book; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cache.CacheManager; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.Optional; +import java.util.UUID; + +import static java.util.Optional.empty; +import static java.util.Optional.ofNullable; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ExtendWith(SpringExtension.class) +@EntityScan(basePackageClasses = Book.class) +@SpringBootTest(classes = CacheApplication.class) +@EnableJpaRepositories(basePackageClasses = BookRepository.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")); + } + + @Test + void givenBookThatShouldBeCachedWhenFindByTitleThenResultShouldBePutInCache() { + Optional dune = repository.findFirstByTitle("Dune"); + + assertEquals(dune, getCachedBook("Dune")); + } + + @Test + void givenBookThatShouldNotBeCachedWhenFindByTitleThenResultShouldNotBePutInCache() { + repository.findFirstByTitle("Foundation"); + + assertEquals(empty(), getCachedBook("Foundation")); + } + + private Optional getCachedBook(String title) { + return ofNullable(cacheManager.getCache("books")).map(c -> c.get(title, Book.class)); + } + +} From e5265b9d23e63ac5cbcfdaf59021dc7ed9471661 Mon Sep 17 00:00:00 2001 From: Adrian Maghear Date: Thu, 4 Jun 2020 22:50:07 +0200 Subject: [PATCH 2/4] [BAEL-3841] fix formatting --- .../baeldung/springdatacaching/repositories/BookRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java b/spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java index d7f80b8b57..4b40fd4060 100644 --- a/spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java +++ b/spring-caching/src/main/java/com/baeldung/springdatacaching/repositories/BookRepository.java @@ -9,7 +9,7 @@ import java.util.UUID; public interface BookRepository extends CrudRepository { - @Cacheable(value = "books", unless="#a0=='Foundation'") + @Cacheable(value = "books", unless = "#a0=='Foundation'") Optional findFirstByTitle(String title); } From 32d6f7df6c511655a78f53ff3400d70224eacdf0 Mon Sep 17 00:00:00 2001 From: Adrian Maghear Date: Sun, 7 Jun 2020 12:28:32 +0200 Subject: [PATCH 3/4] [BAEL-3841] put back the *.sql initialisation files --- spring-caching/pom.xml | 5 +++++ spring-caching/src/main/resources/data.sql | 7 ++++++ spring-caching/src/main/resources/schema.sql | 23 ++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 spring-caching/src/main/resources/data.sql create mode 100644 spring-caching/src/main/resources/schema.sql diff --git a/spring-caching/pom.xml b/spring-caching/pom.xml index 5a320d3048..9a0da2e514 100644 --- a/spring-caching/pom.xml +++ b/spring-caching/pom.xml @@ -67,6 +67,11 @@ org.springframework.boot spring-boot-starter-data-jpa + + net.bytebuddy + byte-buddy + 1.10.10 + org.springframework.data spring-data-commons diff --git a/spring-caching/src/main/resources/data.sql b/spring-caching/src/main/resources/data.sql new file mode 100644 index 0000000000..e4165ae71f --- /dev/null +++ b/spring-caching/src/main/resources/data.sql @@ -0,0 +1,7 @@ +INSERT INTO CUSTOMER VALUES(1001,'BAELDUNG'); + +INSERT INTO ITEM VALUES(10001,'ITEM1',50.0); +INSERT INTO ITEM VALUES(10002,'ITEM2',100.0); + +INSERT INTO ORDERDETAIL VALUES(300001,1001,10001,2); +INSERT INTO ORDERDETAIL VALUES(300002,1001,10002,5); \ No newline at end of file diff --git a/spring-caching/src/main/resources/schema.sql b/spring-caching/src/main/resources/schema.sql new file mode 100644 index 0000000000..35d02bb916 --- /dev/null +++ b/spring-caching/src/main/resources/schema.sql @@ -0,0 +1,23 @@ +DROP TABLE ORDERDETAIL IF EXISTS; +DROP TABLE ITEM IF EXISTS; +DROP TABLE CUSTOMER IF EXISTS; + +CREATE TABLE CUSTOMER( + CUSTOMERID INT PRIMARY KEY, + CUSTOMERNAME VARCHAR(250) NOT NULL +); + +CREATE TABLE ITEM( +ITEMID INT PRIMARY KEY, +ITEMDESC VARCHAR(250), +PRICE DOUBLE +); + +CREATE TABLE ORDERDETAIL( +ORDERID INT PRIMARY KEY, +CUSTOMERID INT NOT NULL, +ITEMID INT NOT NULL, +QUANTITY INT, +FOREIGN KEY (customerid) references CUSTOMER(customerid), +FOREIGN KEY (itemid) references ITEM(itemid) +); \ No newline at end of file From ee694afc51daba4cc90f05fda66b71d25a4252e7 Mon Sep 17 00:00:00 2001 From: Adrian Maghear Date: Wed, 10 Jun 2020 19:44:13 +0200 Subject: [PATCH 4/4] [BAEL-3841] PR review updates --- spring-caching/pom.xml | 2 +- .../repositories/BookRepositoryCachingIntegrationTest.java | 4 ++-- .../repositories/BookRepositoryIntegrationTest.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spring-caching/pom.xml b/spring-caching/pom.xml index 9a0da2e514..b13755dafd 100644 --- a/spring-caching/pom.xml +++ b/spring-caching/pom.xml @@ -70,7 +70,7 @@ net.bytebuddy byte-buddy - 1.10.10 + 1.10.11 org.springframework.data diff --git a/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java b/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java index 49ecc3a058..cd11d7cc4a 100644 --- a/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java +++ b/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryCachingIntegrationTest.java @@ -64,7 +64,7 @@ public class BookRepositoryCachingIntegrationTest { } @Test - void givenCachedBookWhenFindByTitleThenRepositoryShouldNotBeHit() { + void givenCachedBook_whenFindByTitle_thenRepositoryShouldNotBeHit() { assertEquals(of(DUNE), bookRepository.findFirstByTitle("Dune")); verify(mock).findFirstByTitle("Dune"); @@ -75,7 +75,7 @@ public class BookRepositoryCachingIntegrationTest { } @Test - void givenNotCachedBookWhenFindByTitleThenRepositoryShouldBeHit() { + void givenNotCachedBook_whenFindByTitle_thenRepositoryShouldBeHit() { assertEquals(of(FOUNDATION), bookRepository.findFirstByTitle("Foundation")); assertEquals(of(FOUNDATION), bookRepository.findFirstByTitle("Foundation")); assertEquals(of(FOUNDATION), bookRepository.findFirstByTitle("Foundation")); diff --git a/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java b/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java index 56bc898bd0..3d11f4ad0b 100644 --- a/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java +++ b/spring-caching/src/test/java/com/baeldung/springdatacaching/repositories/BookRepositoryIntegrationTest.java @@ -38,14 +38,14 @@ public class BookRepositoryIntegrationTest { } @Test - void givenBookThatShouldBeCachedWhenFindByTitleThenResultShouldBePutInCache() { + void givenBookThatShouldBeCached_whenFindByTitle_thenResultShouldBePutInCache() { Optional dune = repository.findFirstByTitle("Dune"); assertEquals(dune, getCachedBook("Dune")); } @Test - void givenBookThatShouldNotBeCachedWhenFindByTitleThenResultShouldNotBePutInCache() { + void givenBookThatShouldNotBeCached_whenFindByTitle_thenResultShouldNotBePutInCache() { repository.findFirstByTitle("Foundation"); assertEquals(empty(), getCachedBook("Foundation"));