Skip to content

Commit 95cb6ca

Browse files
committed
Polishing.
Simplify code and tests. See #3459 Original pull request: #3461
1 parent 1dfbc01 commit 95cb6ca

File tree

2 files changed

+21
-85
lines changed

2 files changed

+21
-85
lines changed

src/main/java/org/springframework/data/repository/config/DeferredRepositoryInitializationListener.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,12 @@ class DeferredRepositoryInitializationListener implements ApplicationListener<Co
4848
public void onApplicationEvent(ContextRefreshedEvent event) {
4949

5050
ApplicationContext context = event.getApplicationContext();
51-
52-
// Ignore events from child contexts (e.g., Spring Cloud OpenFeign, LoadBalancer)
53-
// to avoid premature repository initialization.
54-
// See https://github.com/spring-projects/spring-boot/commit/708cbd72942e65906ea32ab3204af6c4e58a7314
55-
if (context instanceof ConfigurableApplicationContext cac && cac.getBeanFactory() != beanFactory) {
51+
if (context instanceof ConfigurableApplicationContext cac && !cac.getBeanFactory().equals(beanFactory)) {
5652
return;
5753
}
5854

5955
logger.info("Triggering deferred initialization of Spring Data repositories…");
60-
6156
beanFactory.getBeansOfType(Repository.class);
62-
6357
logger.info("Spring Data repositories initialized");
6458
}
6559

Lines changed: 20 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2018-present the original author or authors.
2+
* Copyright 2026-present the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,11 +19,11 @@
1919

2020
import org.junit.jupiter.api.Test;
2121
import org.junit.jupiter.api.extension.ExtendWith;
22-
import org.mockito.Mock;
2322
import org.mockito.junit.jupiter.MockitoExtension;
2423

2524
import org.springframework.beans.factory.ListableBeanFactory;
2625
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
26+
import org.springframework.context.ApplicationContext;
2727
import org.springframework.context.ConfigurableApplicationContext;
2828
import org.springframework.context.event.ContextRefreshedEvent;
2929
import org.springframework.context.support.GenericApplicationContext;
@@ -32,105 +32,47 @@
3232
/**
3333
* Unit tests for {@link DeferredRepositoryInitializationListener}.
3434
*
35-
* @author Oliver Drotbohm
36-
* @author seongjun-rpls
35+
* @author Seongjun Ha
36+
* @author Mark Paluch
3737
*/
3838
@ExtendWith(MockitoExtension.class)
3939
class DeferredRepositoryInitializationListenerUnitTests {
4040

41-
@Mock ListableBeanFactory beanFactory;
42-
4341
@Test // GH-3459
44-
void triggersInitializationOnMatchingContextEvent() {
45-
46-
var context = new GenericApplicationContext();
47-
context.refresh();
42+
void triggersInitializationCorrectly() {
4843

49-
// Create listener with the real context's BeanFactory
50-
var listener = new DeferredRepositoryInitializationListener(context.getBeanFactory());
44+
var beanFactory = mock(DefaultListableBeanFactory.class);
45+
var context = mock(ApplicationContext.class);
46+
var listener = new DeferredRepositoryInitializationListener(beanFactory);
5147

52-
// Fire event from the same context
5348
listener.onApplicationEvent(new ContextRefreshedEvent(context));
5449

55-
// The test verifies no exception is thrown and listener completes normally
56-
// Since we're using real context, we can't easily mock getBeansOfType
57-
context.close();
50+
verify(beanFactory).getBeansOfType(Repository.class);
5851
}
5952

6053
@Test // GH-3459
61-
void ignoresEventsFromChildContext() {
54+
void triggersInitializationForConfigurableApplicationContext() {
6255

63-
// Mock beanFactory that should NOT be called
64-
ListableBeanFactory mockBeanFactory = mock(ListableBeanFactory.class);
65-
var listener = new DeferredRepositoryInitializationListener(mockBeanFactory);
56+
var beanFactory = mock(DefaultListableBeanFactory.class);
57+
var context = mock(ConfigurableApplicationContext.class);
58+
var listener = new DeferredRepositoryInitializationListener(beanFactory);
59+
when(context.getBeanFactory()).thenReturn(beanFactory);
6660

67-
// Create a real context (will have different beanFactory)
68-
var context = new GenericApplicationContext();
69-
context.refresh();
70-
71-
// Fire event - should be ignored because context.getBeanFactory() != mockBeanFactory
7261
listener.onApplicationEvent(new ContextRefreshedEvent(context));
7362

74-
// Verify the mock was never called
75-
verify(mockBeanFactory, never()).getBeansOfType(Repository.class);
76-
77-
context.close();
63+
verify(beanFactory).getBeansOfType(Repository.class);
7864
}
7965

8066
@Test // GH-3459
81-
void triggersInitializationOnParentContextEvent() {
82-
83-
// Create a mock beanFactory
84-
DefaultListableBeanFactory mockBeanFactory = mock(DefaultListableBeanFactory.class);
85-
86-
// Create a mock ConfigurableApplicationContext
87-
ConfigurableApplicationContext mockContext = mock(ConfigurableApplicationContext.class);
88-
when(mockContext.getBeanFactory()).thenReturn(mockBeanFactory);
67+
void ignoresEventsFromChildContext() {
8968

90-
// Create listener with the same mock beanFactory
91-
var listener = new DeferredRepositoryInitializationListener(mockBeanFactory);
69+
var beanFactory = mock(ListableBeanFactory.class);
70+
var listener = new DeferredRepositoryInitializationListener(beanFactory);
9271

93-
// Fire event from the mock context
94-
listener.onApplicationEvent(new ContextRefreshedEvent(mockContext));
72+
listener.onApplicationEvent(new ContextRefreshedEvent(new GenericApplicationContext()));
9573

96-
// Verify getBeansOfType WAS called
97-
verify(mockBeanFactory).getBeansOfType(Repository.class);
74+
verify(beanFactory, never()).getBeansOfType(Repository.class);
9875
}
9976

100-
@Test // GH-3459
101-
void ignoresEventsFromSiblingChildContexts() {
102-
103-
// Create a mock beanFactory for the "parent" listener
104-
DefaultListableBeanFactory mockParentBeanFactory = mock(DefaultListableBeanFactory.class);
10577

106-
// Create listener as if registered in a parent context
107-
var listener = new DeferredRepositoryInitializationListener(mockParentBeanFactory);
108-
109-
// Create real child contexts (simulates Feign-like scenario)
110-
var childContext1 = new GenericApplicationContext();
111-
childContext1.refresh();
112-
113-
var childContext2 = new GenericApplicationContext();
114-
childContext2.refresh();
115-
116-
// Fire events from child contexts - should be ignored
117-
listener.onApplicationEvent(new ContextRefreshedEvent(childContext1));
118-
listener.onApplicationEvent(new ContextRefreshedEvent(childContext2));
119-
120-
// Verify that getBeansOfType was NOT called for child context events
121-
verify(mockParentBeanFactory, never()).getBeansOfType(Repository.class);
122-
123-
// Now create a mock parent context that returns our mock beanFactory
124-
ConfigurableApplicationContext mockParentContext = mock(ConfigurableApplicationContext.class);
125-
when(mockParentContext.getBeanFactory()).thenReturn(mockParentBeanFactory);
126-
127-
// Fire event from "parent" context
128-
listener.onApplicationEvent(new ContextRefreshedEvent(mockParentContext));
129-
130-
// Verify that getBeansOfType WAS called exactly once for parent context
131-
verify(mockParentBeanFactory, times(1)).getBeansOfType(Repository.class);
132-
133-
childContext1.close();
134-
childContext2.close();
135-
}
13678
}

0 commit comments

Comments
 (0)