Quantcast
Viewing latest article 8
Browse Latest Browse All 14

Answer by krosenvold for Spring beans redefinition in unit test environment

One of the reasons spring is described as test-friendly is because it may be easy to just new or mock stuff in the unit test.

Alternately we have used the following setup with great success, and I think it is quite close to what you want, I would strongly recommend it:

For all beans that need different implementations in different contexts, switch to annotation based wiring. You can leave the others as-is.

Implement the following set of annotations

<context:component-scan base-package="com.foobar"><context:include-filter type="annotation" expression="com.foobar.annotations.StubRepository"/><context:include-filter type="annotation" expression="com.foobar.annotations.TestScopedComponent"/><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/></context:component-scan>

Then you annotate your live implementations with @Repository, your stub implementations with @StubRepository, any code that should be present in the unit-test fixture ONLY with @TestScopedComponent. You may run into needing a couple more annotations, but these are a great start.

If you have a lot of spring.xml, you will probably need to make a few new spring xml files that basically only contain the component-scan definitions. You'd normally just append these files to your regular @ContextConfiguration list. The reason for this is because you frequently end up with different configurations of the context-scans (trust me, you will make at least 1 more annotations if you're doing web-tests, which makes for 4 relevant combinations)

Then you basically use the

@ContextConfiguration(locations = { "classpath:/path/to/root-config.xml" })@RunWith(SpringJUnit4ClassRunner.class)

Note that this setup does not allow you to have alternating combinations of stub/live data. We tried this, and I think that resulted in a mess I wouldn't recommend anyone ;) We either wire inn the full set of stubs or the full set of live services.

We mainly use auto-wired stub dependencies when testing gui near stuff where the dependencies are usually quite substantial. In cleaner areas of the code we use more regular unit-testing.

In our system we have the following xml-files for component-scan:

  • for regular web production
  • for starting web with stubs only
  • for integration tests (in junit)
  • for unit tests (in junit)
  • for selenium web tests (in junit)

This means we totally have 5 different system-wide configurations that we can start the application with. Since we only use annotations, spring is fast enough to autowire even those unit tests we want wired. I know this is untraditional, but it's really great.

Out integration tests run with full live setup, and once or twice I have decided to get really pragmatic and want to have a 5 live wirings and a single mock:

public class HybridTest {   @Autowired   MyTestSubject myTestSubject;   @Test   public void testWith5LiveServicesAndOneMock(){     MyServiceLive service = myTestSubject.getMyService();     try {          MyService mock = EasyMock.create(...)          myTestSubject.setMyService( mock);           .. do funky test  with lots of live but one mock object     } finally {          myTestSubject.setMyService( service);     }   }}

I know the test purists are going to be all over me for this. But sometimes it's just a very pragmatic solution that turns out to be very elegant when the alternative would be really really ugly. Again it's usually in those gui-near areas.


Viewing latest article 8
Browse Latest Browse All 14

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>