package de.flower.common.test.wicket; import de.flower.common.util.Check; import de.flower.common.util.ReflectionUtil; import org.apache.commons.lang.StringUtils; import org.apache.wicket.spring.test.ApplicationContextMock; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import java.util.Map; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.withSettings; /** * Extends wickets ApplicationContextMock by automatically creating mockito mocks whenever * a bean is requested. * Saves developer from adding all mocks to mock context in test-setup. * <p/> * Based on the ideas of http://www.petrikainulainen.net/programming/tips-and-tricks/mocking-spring-beans-with-apache-wicket-and-mockito/. * * @author flowerrrr */ public class MockitoFactoryApplicationContext extends ApplicationContextMock { private final static Logger log = LoggerFactory.getLogger(MockitoFactoryApplicationContext.class); private boolean verboseLogging; protected void createAndAddMock(String name, final Class type) { Check.notNull(type); Object bean; if (verboseLogging) { bean = mock(type, withSettings().verboseLogging()); } else { bean = mock(type); } if (name == null) { name = StringUtils.uncapitalize(type.getSimpleName()); } log.info("Adding new mock [" + name + ", " + type.getName() + "] to mock context."); putBean(name, bean); } @Override public <T> T getBean(final String name, final Class<T> requiredType) throws BeansException { T bean; try { bean = super.getBean(name, requiredType); } catch (BeansException e) { createAndAddMock(name, requiredType); bean = super.getBean(name, requiredType); } return bean; } @Override public String[] getBeanNamesForType(final Class type) { String[] names = super.getBeanNamesForType(type); if (names.length == 0) { createAndAddMock(null, type); // now call will return our bean that we've just created. names = super.getBeanNamesForType(type); } return names; } @Override public <T> Map<String, T> getBeansOfType(final Class<T> type) throws BeansException { Map<String, T> map = super.getBeansOfType(type); if (map.isEmpty()) { createAndAddMock(null, type); map = super.getBeansOfType(type); } return map; } /** * Required for ApplicationContextAwareValidationFactory. * * @return * @throws IllegalStateException */ public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException { return new DefaultListableBeanFactory(); } /** * Return mock for given type. If mock does not exist it will be created. * Use this method to get access to the mocks if changing their behavior is needed. * * @param type * @param <T> * @return */ public <T> T getMock(Class<T> type) { return getBean(type); } public void setVerboseLogging(final boolean verboseLogging) { this.verboseLogging = verboseLogging; } public Map<String, Object> getBeans() { return (Map<String, Object>) ReflectionUtil.getField(this, "beans"); } }