1

There is a spring componet with @Component annotation, it is just java class (not interface) with annotated @Autowired fields. I am trying to create mock like that:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"
    >
  <bean id="myComponent" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg value="com.MyComponent"/>
  </bean>
</beans>

And got an exception that some of fields are not autowired. This happens, because when Spring see <constructor-arg value="com.MyComponent"/> it try to instantiate MyComponent bean and pass it to factory method.

I have tried to extract interface from component, in that case mocking works, but is there a way to make it working without extracting interface?

Also

I have tried adding type="java.lang.Class" but got same errors.

  <bean id="myComponent" class="org.mockito.Mockito" factory-method="mock">
    <constructor-arg  type="java.lang.Class"  value="com.MyComponent"/>
  </bean>

Any ideas?

Cherry
  • 31,309
  • 66
  • 224
  • 364
  • Show us the code of class and the definition of the beans which need to be autowired, please. – Christiaan Janssen Feb 18 '16 at 08:02
  • First of all, with Spring and Mockito, I would always prefer to work with interfaces. In your case, why don't you simply add another (mocked?) bean and insert that into your constructor via `ref`...? But what is the bean you need to put into the constructor really a java.lang.Class object? Sounds strange. – Florian Schaetz Feb 18 '16 at 08:03
  • "why don't you simply add another (mocked?) bean" - it is exactly what is going on at line `class="org.mockito.Mockito" factory-method="mock"` – Cherry Feb 18 '16 at 08:51
  • "But what is the bean you need to put into the constructor really a java.lang.Class object" - see attentively at `class="org.mockito.Mockito" factory-method="mock"`. There is no constrcutor call. There is a factory method call in `Mockito` class. – Cherry Feb 18 '16 at 08:53
  • Sorry, my fault there, wrong thinking. There's a note here http://stackoverflow.com/questions/2457239/injecting-mockito-mocks-into-a-spring-bean , that the declaration has to be before others, but I assume you got that already... – Florian Schaetz Feb 18 '16 at 09:40
  • It works for me, when I do.... ` ` -> Leads to a Mock of TestService, even if TestService is a class and has some `@Autowired` fields declared. Could you add the exception you are getting and the autowwired parts of your `myComponent`? – Florian Schaetz Feb 18 '16 at 09:53

1 Answers1

2

Spring cannot autowire the bean because the type of the created bean is java.lang.Object and not com.myComponent. Apparently the order of the definitions in the XML matters as well.

Jayway has a very nice blog post about this: Spring Integration Tests - Creating Mock Objects

You can create a FactoryBean which returns the correct class:

public class MockitoFactoryBean<T> implements FactoryBean<T> {

    private Class<T> classToBeMocked;

    /**
     * Creates a Mockito mock instance of the provided class.
     * @param classToBeMocked The class to be mocked.
     */
    public MockitoFactoryBean(Class<T> classToBeMocked) {
        this.classToBeMocked = classToBeMocked;
    }

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

    @Override
    public Class<?> getObjectType() {
        return classToBeMocked;
    }

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

Using this factory bean, you can create a config like this:

<bean id="myComponent" class="com.yourpackage.MockitoFactoryBean">
    <constructor-arg name="classToBeMocked" value="com.myComponent" />
</bean>

This will mock your component and the object type will com.myComponent.


Update

This is the original answer and explanation (using EasyMock): Autowiring of beans generated by EasyMock factory-method?

Community
  • 1
  • 1
Tom Verelst
  • 15,324
  • 2
  • 30
  • 40