|
16 | 16 | package org.springframework.data.jpa.repository.support; |
17 | 17 |
|
18 | 18 | import static java.util.Collections.singletonMap; |
| 19 | +import static org.assertj.core.api.Assertions.assertThat; |
19 | 20 | import static org.assertj.core.api.Assertions.assertThatNoException; |
20 | 21 | import static org.mockito.Mockito.any; |
21 | 22 | import static org.mockito.Mockito.never; |
|
31 | 32 | import jakarta.persistence.criteria.CriteriaBuilder; |
32 | 33 | import jakarta.persistence.criteria.CriteriaQuery; |
33 | 34 |
|
| 35 | +import java.lang.reflect.Method; |
| 36 | +import java.lang.reflect.Modifier; |
34 | 37 | import java.util.Arrays; |
| 38 | +import java.util.List; |
35 | 39 | import java.util.Optional; |
| 40 | +import java.util.stream.Stream; |
36 | 41 |
|
37 | 42 | import org.junit.jupiter.api.BeforeEach; |
38 | 43 | import org.junit.jupiter.api.Test; |
39 | 44 | import org.junit.jupiter.api.extension.ExtendWith; |
| 45 | +import org.junit.jupiter.params.ParameterizedTest; |
| 46 | +import org.junit.jupiter.params.provider.MethodSource; |
40 | 47 | import org.mockito.Mock; |
41 | 48 | import org.mockito.junit.jupiter.MockitoExtension; |
42 | 49 | import org.mockito.junit.jupiter.MockitoSettings; |
|
45 | 52 | import org.springframework.data.jpa.domain.sample.User; |
46 | 53 | import org.springframework.data.jpa.repository.EntityGraph.EntityGraphType; |
47 | 54 | import org.springframework.data.repository.CrudRepository; |
| 55 | +import org.springframework.transaction.annotation.Transactional; |
48 | 56 |
|
49 | 57 | /** |
50 | 58 | * Unit tests for {@link SimpleJpaRepository}. |
|
54 | 62 | * @author Mark Paluch |
55 | 63 | * @author Jens Schauder |
56 | 64 | * @author Greg Turnquist |
| 65 | + * @author Yanming Zhou |
57 | 66 | */ |
58 | 67 | @ExtendWith(MockitoExtension.class) |
59 | 68 | @MockitoSettings(strictness = Strictness.LENIENT) |
@@ -216,4 +225,17 @@ void applyQueryHintsToCountQueriesForSpecificationPageables() { |
216 | 225 |
|
217 | 226 | verify(metadata).getQueryHintsForCount(); |
218 | 227 | } |
| 228 | + |
| 229 | + @ParameterizedTest // GH-3188 |
| 230 | + @MethodSource("modifyingMethods") |
| 231 | + void checkTransactionalAnnotation(Method method) { |
| 232 | + Transactional transactional = method.getAnnotation(Transactional.class); |
| 233 | + assertThat(transactional).as("Method [%s] should be annotated with @Transactional", method).isNotNull(); |
| 234 | + assertThat(transactional.readOnly()).as("Method [%s] should not be annotated with @Transactional(readOnly = true)", method).isFalse(); |
| 235 | + } |
| 236 | + |
| 237 | + static List<Method> modifyingMethods() { |
| 238 | + return Stream.of(SimpleJpaRepository.class.getDeclaredMethods()).filter(method -> Modifier.isPublic(method.getModifiers()) && |
| 239 | + !method.isBridge() && (method.getName().startsWith("delete") || method.getName().startsWith("save"))).toList(); |
| 240 | + } |
219 | 241 | } |
0 commit comments