Compatible with Spring >= 4.3 (so spring-boot >= 1.4)
PoC of automatic IO mocking tool for Spring's JavaConfig.
Load your entire Production configuration into a JUnit test.
The purpose of this project is to test functionalities of applications on real code without heavy glue code.
Currently the project supports mocking of
Use SpringJUnit4ClassRunner in conjunction with @Automocker
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MyApplication.class)
@Automocker
public class MyApplicationTest {
@Autowired
private MockMvc mockMvc;
@Test
public void user_creation_api() {
mvc.perform(MockMvcRequestBuilders.get("/create_user?firstName=Alyson&lastName=Hannigan"))
.andExpect(MockMvcResultMatchers.status().isOk());
mvc.perform(MockMvcRequestBuilders.get("/list_users"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().string("[\"Alyson Hannigan\"]"));
}
}There is nothing to mock here. However some things are nonetheless being taken care of
- If any bean annotated with spring-context
@Controlleris present, spring-testMockMvcis configured and added to the test context
All beans implementing javax.sql.DataSource are replaced with distinct org.h2.jdbcx.JdbcDataSource.
A DataSourceLocator bean is supplied to easily access multiple dataSources.
- All beans implementing
javax.jms.ConnectionFactoryare replaced by a mockrunnerMockConnectionFactory. Each factory is built with its ownDestinationManager - If any bean implementing
javax.jms.ConnectionFactoryis present, a customJmsMockis configured and added to the test context - If any bean implementing spring-jms
JmsListenerContainerFactoryis present, a wrapper is set around itsErrorHandlerand can be accessed throughJmsMock - A
JmsMockLocatorbean is supplied to easily access multipleJmsMock.
A test class meta-annotated with @AfterBeanRegistration will trigger specific behavior through the indicated AfterBeanRegistrationExecutable implementation.
This annotation can only be used on an annotation as the AfterBeanRegistrationExecutable#execute will be supplied with the annotation annotated with AfterBeanRegistration.
Doing so the developper can defined specific arguments in the annotation, such as @MockJdbc#url() and used them in the AfterBeanRegistrationExecutable implementation.
For example, replacing user-defined beans by Mockito mocks can be done like this:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@AfterBeanRegistration(MockBeans.MockBeansExecutable.class)
public @interface MockBeans {
Class<?>[] classes();
class MockBeansExecutable implements AfterBeanRegistrationExecutable<MockBeans> {
@Override
public void execute(MockBeans annotation, ExtendedBeanDefinitionRegistry extendedBeanDefinitionRegistry) {
String mockCreatorBeanName = extendedBeanDefinitionRegistry.registerBeanDefinition(MockCreator.class);
Arrays.stream(annotation.classes())
.map(extendedBeanDefinitionRegistry::getBeanDefinitionsForClass)
.flatMap(Set::stream)
.forEach(bean -> replaceDefinitionByMock(mockCreatorBeanName, bean));
}
private static void replaceDefinitionByMock(String mockCreatorBeanName, BeanDefinitionMetadata beanDefinitionMetadata) {
beanDefinitionMetadata.beanDefinitionModifier()
.setFactoryBeanName(mockCreatorBeanName)
.setFactoryMethodName("createMock")
.addIndexedArgumentValue(0, beanDefinitionMetadata.beanClass());
}
}
class MockCreator {
@Bean
public <T> T createMock(Class<T> clazz) {
return Mockito.mock(clazz);
}
}
}Usage is then pretty simple:
@ContextConfiguration(classes = SimpleApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
@MockBeans(classes = MyBean.class)
public class SimpleApplicationTest {
@Autowired
private MyBean myMock;
...