javalearner
javalearner

Reputation: 3382

Spring @Value annotation not working with mockito mock

I am using spring @Value annotation and setting values for some fields in class A.

I am writing unit tests for this class A. In the test class, I am annotating the reference for class A with Mockito @Spy. I am setting the values as system properties and then invoking MockitoAnnotations.initMocks(this).

My expectation is the spied object will have the fields initialized with the values from system properties via @Value annotation. But this is not happening.

Please anybody could explain?

Upvotes: 3

Views: 9791

Answers (2)

bric3
bric3

Reputation: 42283

Mockito is not Spring aware! And will never be! You'll always have to init these kind of injection yourself as it is not pure java.

However you can take a look at springockito, it is a spring extension that enable some interesting usage of Mockito with Spring. But you'll have to create a Spring context for the test.

Note that using a spring context in a JUnit test is like crafting an integration test.

Upvotes: 3

Francisco Spaeth
Francisco Spaeth

Reputation: 23913

I have a similar test and I'm using the following relevant code:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/context.xml")
public class ContextTest {

    private boolean started = false;

    @Spy
    @Autowired
    private Baz baz;

    @Before
    public void before() {
        if (!started) {
            MockitoAnnotations.initMocks(this);
            started = true;
        }
    }

    @Test
    public void spy() {
        Assert.assertEquals("value", baz.getProperty());
        Mockito.verify(baz).getProperty();
    }

}

Basically it will let spring process the test annotations (due to SpringJUnitRunner) and afterwards let Mockito process them (explicitly invoked MockitoAnnotations.initMocks(instanceOfTestClass)).


Other files to have a complete test

simple Baz.java spring class:

package foo.bar;

import org.springframework.beans.factory.annotation.Value;

public class Baz {

    @Value("${property:test}")
    private String property;

    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }

}

the context.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>my.properties</value>
        </property>
    </bean>

    <bean id="baz" class="foo.bar.Baz" />

</beans>

my.property file:

property=value

and the maven (pom.xml) file:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>spring-test</groupId>
    <artifactId>my.spring.test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>3.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>3.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>3.2.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.9.5</version>
                    <scope>test</scope>
        </dependency>
    </dependencies>
</project>

the file structure is:

+ spring-test
  - pom.xml
  + src/main/java
      + foo.bar
         - Baz.java
  + src/main/resources
      - context.xml
      - my.properties
  + src/test/java
      + foo.bar
         - ContextTest.java

Upvotes: 3

Related Questions