7

I am a Spring neophyte who is working on a large Spring-based project that has extensive coupling between Spring beans. I am trying to write some integration tests that exercise subsets of the total application functionality. To do so, I'd like to override some of the autowiring. For example, suppose I have a class

public class MyDataServiceImpl implements MyDataService {
    @Qualifier("notNeededForMyDataServiceTest")
    @Autowired
    private NotNeededForMyDataServiceTest notNeededForMyDataServiceTest;
    //...
}

and a context file with:

<bean id="myDataService"
      class="MyDataServiceImpl">
</bean>

In my test, I have no need to use the notNeededForMyDataServiceTest field. Is there some way I can override the @Autowired annotation and set notNeededForMyDataServiceTest to null, perhaps in the XML file? I don't want to modify any of the Java classes, but I do want to avoid the (problematic) configuration of notNeededForMyDataServiceTest.

I tried doing:

<bean id="myDataService"
      class="MyDataServiceImpl">
    <property name="notNeededForMyDataServiceTest"><null/></property>
</bean>

That doesn't work. IntelliJ informs me "Cannot resolve property 'notNeededForMyDataServiceTest'", apparently because there are no getters and setters for that field.

I'm using Spring Framework 3.1.3.

kc2001
  • 5,008
  • 4
  • 51
  • 92
  • did you try: , I think this will give you a string null but you can at least set a value – Jayz Jul 25 '13 at 18:35

3 Answers3

5

The following configuration should work, I took the liberty of mixing in Java configuration

@Configuration
//This will load your beans from whichever xml file you are using
@ImportResource("classpath:/path/beans.xml")
public class TestConfigLoader{
    // This will declare the unused bean and inject MyDataServiceImpl with null.
    public @Bean(name="notNeededForMyDataServiceTest") NotNeededForMyDataServiceTest getNotNeededForMyDataServiceTest(){
        return null;
    }
... any other configuration beans if required.
}

And annotate your test class like so:

// In your test class applicationContext will be loaded from TestConfigLoader
@ContextConfiguration(classes = {TestConfigLoader.class})
public class MyTest {
    // class body...
}
kc2001
  • 5,008
  • 4
  • 51
  • 92
Abe
  • 8,623
  • 10
  • 50
  • 74
3

These could help:

and profiles:

You could create different beans definition in the XML configuration and then activate them using the -Dspring.profiles.active="profile1,profile2" env.

David Riccitelli
  • 7,491
  • 5
  • 42
  • 56
3

You're using the @Autowired mechanism wrong. The qualifier is not a property that you need to set. That's actually the name of a bean, so that the container will be able to choose one particular instance in case multiple beans of the same type are defined in the same context.

So the container will look for a bean of type NotNeededForMyDataServiceTest and the name (which would actually be the bean id in XML): notNeededForMyDataServiceTest.

What I think you want is to instruct the container to not inject anything in that field if no bean of type NotNeededForMyDataServiceTest is defined in the application context. That could be achieved simply by setting the required attribute of the annotation to false:

@Autowired(required = false)
NotNeededForMyDataServiceTest someOptionalDependency;

The only drawback of this approach would be that the container will never complain at runtime if there's nothing to inject in that field (and perhaps you would want this sanity check when your code runs in production).


If you don't want to make that dependency optional (or you can't edit that code for some reason), you'll need to provide a mock / null value for that field by setting that explicitly in your context. One option to do that would be to use Java configuration instead of XML (like in @Abe's answer) and another approach would be to make use of a factory bean which returns null (like in this question).

Community
  • 1
  • 1
Costi Ciudatu
  • 37,042
  • 7
  • 56
  • 92
  • Thanks for your response. Unfortunately, you're right - we do want the sanity check in production. – kc2001 Aug 12 '13 at 18:04
  • Thanks! I would like to split the bonus between your answer and Abe's, but I can't. I'm giving the bonus to Abe, because he provided a code example. – kc2001 Aug 13 '13 at 14:08