Test MockReset strategy for @MockitoSpyBean
As a follow up to commit 0088b9c7f8, this commit introduces an
integration test which verifies that a spy created via @MockitoSpyBean
using the MockReset.AFTER strategy is not reset between the refresh of
the ApplicationContext and the first use of the spy within a @Test
method.
See gh-33941
See gh-33986
			
			
This commit is contained in:
		
							parent
							
								
									ddec8d2653
								
							
						
					
					
						commit
						51956fad89
					
				|  | @ -17,6 +17,7 @@ | ||||||
| package org.springframework.test.context.bean.override.mockito.integration; | package org.springframework.test.context.bean.override.mockito.integration; | ||||||
| 
 | 
 | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
|  | import org.mockito.Mockito; | ||||||
| 
 | 
 | ||||||
| import org.springframework.context.event.ContextRefreshedEvent; | import org.springframework.context.event.ContextRefreshedEvent; | ||||||
| import org.springframework.context.event.EventListener; | import org.springframework.context.event.EventListener; | ||||||
|  | @ -25,6 +26,7 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean; | ||||||
| import org.springframework.test.context.bean.override.mockito.integration.MockitoBeanUsedDuringApplicationContextRefreshIntegrationTests.ContextRefreshedEventListener; | import org.springframework.test.context.bean.override.mockito.integration.MockitoBeanUsedDuringApplicationContextRefreshIntegrationTests.ContextRefreshedEventListener; | ||||||
| import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; | import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; | ||||||
| 
 | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
| import static org.mockito.ArgumentMatchers.any; | import static org.mockito.ArgumentMatchers.any; | ||||||
| import static org.mockito.BDDMockito.then; | import static org.mockito.BDDMockito.then; | ||||||
| 
 | 
 | ||||||
|  | @ -35,6 +37,7 @@ import static org.mockito.BDDMockito.then; | ||||||
|  * @author Sam Brannen |  * @author Sam Brannen | ||||||
|  * @author Yanming Zhou |  * @author Yanming Zhou | ||||||
|  * @since 6.2.1 |  * @since 6.2.1 | ||||||
|  |  * @see MockitoSpyBeanUsedDuringApplicationContextRefreshIntegrationTests | ||||||
|  */ |  */ | ||||||
| @SpringJUnitConfig(ContextRefreshedEventListener.class) | @SpringJUnitConfig(ContextRefreshedEventListener.class) | ||||||
| class MockitoBeanUsedDuringApplicationContextRefreshIntegrationTests { | class MockitoBeanUsedDuringApplicationContextRefreshIntegrationTests { | ||||||
|  | @ -45,6 +48,8 @@ class MockitoBeanUsedDuringApplicationContextRefreshIntegrationTests { | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	void test() { | 	void test() { | ||||||
|  | 		assertThat(Mockito.mockingDetails(eventProcessor).isMock()).as("isMock").isTrue(); | ||||||
|  | 		assertThat(Mockito.mockingDetails(eventProcessor).isSpy()).as("isSpy").isFalse(); | ||||||
| 		// Ensure that the mock was invoked during ApplicationContext refresh | 		// Ensure that the mock was invoked during ApplicationContext refresh | ||||||
| 		// and has not been reset in the interim. | 		// and has not been reset in the interim. | ||||||
| 		then(eventProcessor).should().process(any(ContextRefreshedEvent.class)); | 		then(eventProcessor).should().process(any(ContextRefreshedEvent.class)); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,98 @@ | ||||||
|  | /* | ||||||
|  |  * Copyright 2002-2024 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. | ||||||
|  |  * You may obtain a copy of the License at | ||||||
|  |  * | ||||||
|  |  *      https://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  |  * | ||||||
|  |  * Unless required by applicable law or agreed to in writing, software | ||||||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |  * See the License for the specific language governing permissions and | ||||||
|  |  * limitations under the License. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | package org.springframework.test.context.bean.override.mockito.integration; | ||||||
|  | 
 | ||||||
|  | import org.junit.jupiter.api.AfterAll; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.mockito.Mockito; | ||||||
|  | 
 | ||||||
|  | import org.springframework.context.annotation.Bean; | ||||||
|  | import org.springframework.context.annotation.Configuration; | ||||||
|  | import org.springframework.context.annotation.Import; | ||||||
|  | import org.springframework.context.event.ContextRefreshedEvent; | ||||||
|  | import org.springframework.context.event.EventListener; | ||||||
|  | import org.springframework.stereotype.Component; | ||||||
|  | import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; | ||||||
|  | import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; | ||||||
|  | 
 | ||||||
|  | import static org.assertj.core.api.Assertions.assertThat; | ||||||
|  | import static org.mockito.ArgumentMatchers.same; | ||||||
|  | import static org.mockito.BDDMockito.then; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Integration tests for {@link MockitoSpyBean @MockitoSpyBean} used during | ||||||
|  |  * {@code ApplicationContext} refresh. | ||||||
|  |  * | ||||||
|  |  * @author Sam Brannen | ||||||
|  |  * @since 6.2.1 | ||||||
|  |  * @see MockitoBeanUsedDuringApplicationContextRefreshIntegrationTests | ||||||
|  |  */ | ||||||
|  | @SpringJUnitConfig | ||||||
|  | class MockitoSpyBeanUsedDuringApplicationContextRefreshIntegrationTests { | ||||||
|  | 
 | ||||||
|  | 	static ContextRefreshedEvent contextRefreshedEvent; | ||||||
|  | 
 | ||||||
|  | 	@MockitoSpyBean | ||||||
|  | 	ContextRefreshedEventProcessor eventProcessor; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	@AfterAll | ||||||
|  | 	static void clearStaticField() { | ||||||
|  | 		contextRefreshedEvent = null; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	void test() { | ||||||
|  | 		assertThat(Mockito.mockingDetails(eventProcessor).isSpy()).as("isSpy").isTrue(); | ||||||
|  | 		// Ensure that the spy was invoked during ApplicationContext refresh | ||||||
|  | 		// and has not been reset in the interim. | ||||||
|  | 		then(eventProcessor).should().process(same(contextRefreshedEvent)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	@Configuration | ||||||
|  | 	@Import(ContextRefreshedEventListener.class) | ||||||
|  | 	static class Config { | ||||||
|  | 
 | ||||||
|  | 		@Bean | ||||||
|  | 		ContextRefreshedEventProcessor eventProcessor() { | ||||||
|  | 			// Cannot be a lambda expression, since Mockito cannot create a spy for a lambda. | ||||||
|  | 			return new ContextRefreshedEventProcessor() { | ||||||
|  | 
 | ||||||
|  | 				@Override | ||||||
|  | 				public void process(ContextRefreshedEvent event) { | ||||||
|  | 					contextRefreshedEvent = event; | ||||||
|  | 				} | ||||||
|  | 			}; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	interface ContextRefreshedEventProcessor { | ||||||
|  | 		void process(ContextRefreshedEvent event); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// MUST be annotated with @Component, due to EventListenerMethodProcessor.isSpringContainerClass(). | ||||||
|  | 	@Component | ||||||
|  | 	record ContextRefreshedEventListener(ContextRefreshedEventProcessor contextRefreshedEventProcessor) { | ||||||
|  | 
 | ||||||
|  | 		@EventListener | ||||||
|  | 		void onApplicationEvent(ContextRefreshedEvent event) { | ||||||
|  | 			this.contextRefreshedEventProcessor.process(event); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue