5

How would you go about integration testing a spring application that is annotation-configured and component-scanned and does not have an XML configuration at all? I'm hitting a wall with the need to replace production components with testing components without actually resorting to xml configuration or reflection injections to all the @autowired parts.

Example:

interface A {...}

@Component
class AImpl implements A {
    ...
}


interface B {...}

@Component 
class BImpl implements B {
    @Autowired A a;
    ...
}


interface C {...}

class CImpl implements C {
    @Autowired B b;
    ...
}

then in my test I want to use ATestImpl, but I only have access to C (integration testing C).

How would you go about doing that?

0

5 Answers 5

10

Take advantage of @Primary annotation:

@Service
@Primary
public class TestA implements A {
  //...
}

If there is more than one bean implementing A, Spring will prefer the one annotated with @Primary. If you place TestA class in /src/test/java, it will only be picked up during test execution, on normal context startup Spring won't see TestA and use only avaialble AImpl.

Sign up to request clarification or add additional context in comments.

2 Comments

oooh. nice. Didn't know that even exist. Thanks! I'll mark this as accepted once I verify and understand how to use one "primary" service for one test, and another for another test (e.g. ATestImpl1 and ATestImpl2).
Using different implementations for different tests might be tricky: I guess you are searching for beans through CLASSPATH scanning and if Spring finds more than one @Primary service you're in trouble.
2

Use a dedicated spring context XML file where you override AImpl with an instance of ATestImpl. Of course, it uses XML, but I don't see any other solution (other than repackaging the application with your ATestImpl annotated class instead of the AImpl one)

2 Comments

+1, I'd prefer to use a test XML, @Primary not always work as expected.
I went through all the trouble of using annotations to avoid adding XMLs to my project. Why would I want to add them to the tests? That would require me (and all other developers) to learn and maintain TWO different configuration mechanisms - XML and annotations.
1

The new Bean Profile features in Spring 3.1 address the need to swap injected components for testing by defining profiles e.g. test, production etc.

The link to the blog post is here. The Spring team have today released the second milestone release of Spring 3.1.

1 Comment

Interesting. still not in release though. Pity.
1

You can use a special component scan for your test, that exclude the "normal" class and add the test class.

If you have several different test classes, then they should not have a @Component Annotation (or @Service, ...). Instead they should be loaded by an XML Bean declaration. So you can have different XML files for different setups.

<context:component-scan base-package="com.queomedia.sgcrm.base">
    <context:exclude-filter expression="com\.example\.AImpl" type="regex"/>
</context:component-scan>

<bean class="com.example.ATestImpl"/>

Comments

1

Using Spring annotation config classes, code the @Bean methods to interfaces. The prod config can perform a componentscan on the high-level package(s) to load the prod objects and the test configs can individually specify beans to return the test versions of your objects. This works very well for component testing where faking service calls and DAO objects is necessary.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.