4

I'd like to continue this question.

These answers foo and bar are exactly what I would need.

But for the bar example spring doesn't infer the type of bean that is returned from generic mock() method. But actually it's exactly the same as in the MockFactoryBean case, that is working.

class MockFactoryBean<T> implements FactoryBean<T> {

    private Class<T> type;

    public void setType(final Class<T> type) {
        this.type = type;
    }

    @Override
    public T getObject() throws Exception {
        return (T) Mockito.mock(type);
    }

    @Override
    public Class<T> getObjectType() {
        return type;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

plus

<bean id="mockFactory" name="someType" class="com.example.MocksFactory" >
    <property name="type" value="com.example.SomeType" />
</bean>

BUT using org.mockito.Mockito and mock() factory method doesn't work

<bean id="dao" class="org.mockito.Mockito" factory-method="mock"> 
    <constructor-arg value="com.example.SomeType" /> 
</bean> 

and one gets No matching bean of type [ com.example.SomeType ] ... when Autowiring.

@Autowired public SomeType someType;

Why is that ?

the way with MockFactoryBean is quite inconvenient because if you have to mock many beans, you end up like this :

<bean id="mockFactory1" name="metadataExtractor" class="tests.base.MocksFactory" >
    <property name="type" value="processing.MetadataExtractor" />
</bean>
<bean id="mockFactory2" name="fileValidator" class="tests.base.MocksFactory" >
    <property name="type" value="validation.file.FileValidator" />
</bean>
<bean id="mockFactory3" name="documentMatcher" class="tests.base.MocksFactory" >
    <property name="type" value="validation.matching.DocumentMatcher" />
</bean>
<bean id="mockFactory4" name="uploadMatcher" class="tests.base.MocksFactory">
    <property name="type" value="validation.matching.UploadMatcher" />
</bean>
<bean id="mockFactory5" name="tempFileLocalService" class="tests.base.MocksFactory">
    <property name="type" value="service.TempFileLocalService" />
</bean>
<bean id="mockFactory6" name="orderLocalService" class="tests.base.MocksFactory">
    <property name="type" value="service.OrderLocalService" />
</bean>
<bean id="mockFactory7" name="counterLocalService" class="tests.base.MocksFactory">
    <property name="type" value="service.CounterLocalService" />
</bean>

Because without id & name it doesn't infer the type.

Community
  • 1
  • 1
lisak
  • 21,611
  • 40
  • 152
  • 243
  • [This](http://stackoverflow.com/a/12352317/448078) example works for me pretty cool. – Mike Dec 02 '14 at 16:38

3 Answers3

7

When XML file should work with standard spring/mockito jars you can use ProxyFactoryBean and it works with autowiring (tested on Spring 2.5).

<bean id="dao" class="org.springframework.aop.framework.ProxyFactoryBean">
   <property name="target"> <bean class="org.mockito.Mockito" factory-method="mock"> <constructor-arg value="com.package.Dao" /> </bean> </property>
   <property name="proxyInterfaces"> <value>com.package.Dao</value> </property>
</bean> 
Kamil
  • 161
  • 1
  • 2
0

What I came up with:

public class SpringMocks implements ApplicationContextAware {

    private static final Logger logger = LoggerFactory.getLogger(SpringMocks.class);
    private final List<Class<?>> classes;

    public SpringMocks(List<Class<?>> classes) {
        this.classes = classes;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (applicationContext instanceof GenericApplicationContext) {
            GenericApplicationContext context = (GenericApplicationContext) applicationContext;
            DefaultListableBeanFactory beanFactory = context.getDefaultListableBeanFactory();

            for (Class<?> className : classes) {
                String beanName = RandomStringUtils.randomAlphanumeric(10);
                Object singletonObject = Mockito.mock(className);
                beanFactory.registerSingleton(beanName, singletonObject);
            }
        } else {
            logger.warn("unable to add beans to the context!");
        }
    }
}

And the definition:

<bean class="com.whatever.SpringMocks">
    <constructor-arg index="0">
        <list>
            <value>com.whatever.enricher.Enricher</value>
            <value>com.whatever.nimbus.NimbusOrderDao</value>
            <value>com.whatever.nimbus.NimbusAllocationDao</value>
            <value>com.whatever.nimbus.NimbusExecutionDao</value>
            <value>com.whatever.nimbus.NimbusBookingInstructionDao</value>
            <value>com.whatever.services.SettingsService</value>
            <value>com.whatever.matchers.utils.CVDataRetriever</value>
        </list>
    </constructor-arg>
</bean>

Hope it will help those who are looking for the solution

Alexey Grigorev
  • 2,415
  • 28
  • 47
0

I take that a step further with a bit more code in the FactoryBean and keep the real mock creation in my test class. Instead, my FactoryBean generates dynamic proxies as needed on Spring startup--which don't suffer the typing problem you're seeing--and the tests can wire in mocks as desired. I wrote a blog post that describes how to do it. The post specifically deals with testing a JAX-RS resource class, but the last section can pretty much stand on its own as an alternate way of doing what you're attempting if you blur out the JAX-RS stuff.

Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199
  • it's nicely done but I got used to leave behind only solutions that are obvious on the first sight. This demands a lot of concentration to even get it and it will so repeatedly for other programmers and me myself after some time :-) – lisak Aug 08 '11 at 07:31
  • @lisak: I enjoy using it for exactly the opposite reason: it lets you keep writing tests the same way as usual, so there's nothing new to get used to. – Ryan Stewart Aug 08 '11 at 22:55