|
|
|
|
@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
|
|
|
|
|
/* |
|
|
|
|
* Copyright 2018-present the original author or authors. |
|
|
|
|
* Copyright 2026-present the original author or authors. |
|
|
|
|
* |
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
|
@ -19,11 +19,11 @@ import static org.mockito.Mockito.*;
@@ -19,11 +19,11 @@ import static org.mockito.Mockito.*;
|
|
|
|
|
|
|
|
|
|
import org.junit.jupiter.api.Test; |
|
|
|
|
import org.junit.jupiter.api.extension.ExtendWith; |
|
|
|
|
import org.mockito.Mock; |
|
|
|
|
import org.mockito.junit.jupiter.MockitoExtension; |
|
|
|
|
|
|
|
|
|
import org.springframework.beans.factory.ListableBeanFactory; |
|
|
|
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory; |
|
|
|
|
import org.springframework.context.ApplicationContext; |
|
|
|
|
import org.springframework.context.ConfigurableApplicationContext; |
|
|
|
|
import org.springframework.context.event.ContextRefreshedEvent; |
|
|
|
|
import org.springframework.context.support.GenericApplicationContext; |
|
|
|
|
@ -32,105 +32,47 @@ import org.springframework.data.repository.Repository;
@@ -32,105 +32,47 @@ import org.springframework.data.repository.Repository;
|
|
|
|
|
/** |
|
|
|
|
* Unit tests for {@link DeferredRepositoryInitializationListener}. |
|
|
|
|
* |
|
|
|
|
* @author Oliver Drotbohm |
|
|
|
|
* @author seongjun-rpls |
|
|
|
|
* @author Seongjun Ha |
|
|
|
|
* @author Mark Paluch |
|
|
|
|
*/ |
|
|
|
|
@ExtendWith(MockitoExtension.class) |
|
|
|
|
class DeferredRepositoryInitializationListenerUnitTests { |
|
|
|
|
|
|
|
|
|
@Mock ListableBeanFactory beanFactory; |
|
|
|
|
|
|
|
|
|
@Test // GH-3459
|
|
|
|
|
void triggersInitializationOnMatchingContextEvent() { |
|
|
|
|
|
|
|
|
|
var context = new GenericApplicationContext(); |
|
|
|
|
context.refresh(); |
|
|
|
|
void triggersInitializationCorrectly() { |
|
|
|
|
|
|
|
|
|
// Create listener with the real context's BeanFactory
|
|
|
|
|
var listener = new DeferredRepositoryInitializationListener(context.getBeanFactory()); |
|
|
|
|
var beanFactory = mock(DefaultListableBeanFactory.class); |
|
|
|
|
var context = mock(ApplicationContext.class); |
|
|
|
|
var listener = new DeferredRepositoryInitializationListener(beanFactory); |
|
|
|
|
|
|
|
|
|
// Fire event from the same context
|
|
|
|
|
listener.onApplicationEvent(new ContextRefreshedEvent(context)); |
|
|
|
|
|
|
|
|
|
// The test verifies no exception is thrown and listener completes normally
|
|
|
|
|
// Since we're using real context, we can't easily mock getBeansOfType
|
|
|
|
|
context.close(); |
|
|
|
|
verify(beanFactory).getBeansOfType(Repository.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test // GH-3459
|
|
|
|
|
void ignoresEventsFromChildContext() { |
|
|
|
|
void triggersInitializationForConfigurableApplicationContext() { |
|
|
|
|
|
|
|
|
|
// Mock beanFactory that should NOT be called
|
|
|
|
|
ListableBeanFactory mockBeanFactory = mock(ListableBeanFactory.class); |
|
|
|
|
var listener = new DeferredRepositoryInitializationListener(mockBeanFactory); |
|
|
|
|
var beanFactory = mock(DefaultListableBeanFactory.class); |
|
|
|
|
var context = mock(ConfigurableApplicationContext.class); |
|
|
|
|
var listener = new DeferredRepositoryInitializationListener(beanFactory); |
|
|
|
|
when(context.getBeanFactory()).thenReturn(beanFactory); |
|
|
|
|
|
|
|
|
|
// Create a real context (will have different beanFactory)
|
|
|
|
|
var context = new GenericApplicationContext(); |
|
|
|
|
context.refresh(); |
|
|
|
|
|
|
|
|
|
// Fire event - should be ignored because context.getBeanFactory() != mockBeanFactory
|
|
|
|
|
listener.onApplicationEvent(new ContextRefreshedEvent(context)); |
|
|
|
|
|
|
|
|
|
// Verify the mock was never called
|
|
|
|
|
verify(mockBeanFactory, never()).getBeansOfType(Repository.class); |
|
|
|
|
|
|
|
|
|
context.close(); |
|
|
|
|
verify(beanFactory).getBeansOfType(Repository.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test // GH-3459
|
|
|
|
|
void triggersInitializationOnParentContextEvent() { |
|
|
|
|
|
|
|
|
|
// Create a mock beanFactory
|
|
|
|
|
DefaultListableBeanFactory mockBeanFactory = mock(DefaultListableBeanFactory.class); |
|
|
|
|
|
|
|
|
|
// Create a mock ConfigurableApplicationContext
|
|
|
|
|
ConfigurableApplicationContext mockContext = mock(ConfigurableApplicationContext.class); |
|
|
|
|
when(mockContext.getBeanFactory()).thenReturn(mockBeanFactory); |
|
|
|
|
void ignoresEventsFromChildContext() { |
|
|
|
|
|
|
|
|
|
// Create listener with the same mock beanFactory
|
|
|
|
|
var listener = new DeferredRepositoryInitializationListener(mockBeanFactory); |
|
|
|
|
var beanFactory = mock(ListableBeanFactory.class); |
|
|
|
|
var listener = new DeferredRepositoryInitializationListener(beanFactory); |
|
|
|
|
|
|
|
|
|
// Fire event from the mock context
|
|
|
|
|
listener.onApplicationEvent(new ContextRefreshedEvent(mockContext)); |
|
|
|
|
listener.onApplicationEvent(new ContextRefreshedEvent(new GenericApplicationContext())); |
|
|
|
|
|
|
|
|
|
// Verify getBeansOfType WAS called
|
|
|
|
|
verify(mockBeanFactory).getBeansOfType(Repository.class); |
|
|
|
|
verify(beanFactory, never()).getBeansOfType(Repository.class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test // GH-3459
|
|
|
|
|
void ignoresEventsFromSiblingChildContexts() { |
|
|
|
|
|
|
|
|
|
// Create a mock beanFactory for the "parent" listener
|
|
|
|
|
DefaultListableBeanFactory mockParentBeanFactory = mock(DefaultListableBeanFactory.class); |
|
|
|
|
|
|
|
|
|
// Create listener as if registered in a parent context
|
|
|
|
|
var listener = new DeferredRepositoryInitializationListener(mockParentBeanFactory); |
|
|
|
|
|
|
|
|
|
// Create real child contexts (simulates Feign-like scenario)
|
|
|
|
|
var childContext1 = new GenericApplicationContext(); |
|
|
|
|
childContext1.refresh(); |
|
|
|
|
|
|
|
|
|
var childContext2 = new GenericApplicationContext(); |
|
|
|
|
childContext2.refresh(); |
|
|
|
|
|
|
|
|
|
// Fire events from child contexts - should be ignored
|
|
|
|
|
listener.onApplicationEvent(new ContextRefreshedEvent(childContext1)); |
|
|
|
|
listener.onApplicationEvent(new ContextRefreshedEvent(childContext2)); |
|
|
|
|
|
|
|
|
|
// Verify that getBeansOfType was NOT called for child context events
|
|
|
|
|
verify(mockParentBeanFactory, never()).getBeansOfType(Repository.class); |
|
|
|
|
|
|
|
|
|
// Now create a mock parent context that returns our mock beanFactory
|
|
|
|
|
ConfigurableApplicationContext mockParentContext = mock(ConfigurableApplicationContext.class); |
|
|
|
|
when(mockParentContext.getBeanFactory()).thenReturn(mockParentBeanFactory); |
|
|
|
|
|
|
|
|
|
// Fire event from "parent" context
|
|
|
|
|
listener.onApplicationEvent(new ContextRefreshedEvent(mockParentContext)); |
|
|
|
|
|
|
|
|
|
// Verify that getBeansOfType WAS called exactly once for parent context
|
|
|
|
|
verify(mockParentBeanFactory, times(1)).getBeansOfType(Repository.class); |
|
|
|
|
|
|
|
|
|
childContext1.close(); |
|
|
|
|
childContext2.close(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|