3

I'm working on an application which has both component and integration tests. The differences between then is: a component test test more than one class (i.e., its inner objects aren't all mocked out - but some of them might be [such as JMS publishers]) and an Integration test is a test that nothing at all is mocked out. In another words, Spring gives you the object and you test it as it is.

So far, so good.

The problem is: in order to be able to replace one dependency or another from the Spring context, I used Springockito (https://bitbucket.org/kubek2k/springockito/wiki/Home) which offers you a way to mock out some bean from the Spring context.

So - in the component tests - I have this:

@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext(classMode = AFTER_CLASS)
@ContextConfiguration(loader = SpringockitoContextLoader.class, locations = "classpath:spring-classify-test.xml")
public class....

     @Autowired
     @ReplaceWithMock
     private SomeServiceInterface someServiceInterface;
     @Autowired
     private Bean bean;

Bean has SomeServiceInterface as a depedency.

public class Bean { 
   private SomeServiceInterface...

In the case above, SomeServiceInterface will be replaced by a mock. Of course, that example is an oversimplification of the problem - I replace bean with mock objects that are dependecies further down in the object graph.

It's worthy noticing that I load the context from this file: spring-classify-test.xml Also it's wothy noticing that I mark the context as dirty after the execution of the class - so, AFAIK, the next test class must reload the context.

Now the integration test:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = SpringockitoContextLoader.class, locations = {"classpath:/spring-service-integration-test.xml" })
public class ...

    @Autowired
    private Bean bean;

I load the context from spring-service-integration-test.xml - but SomeServiceInterface inside of Bean is still mocked! The context used in the integration test was changed as well!

If I mark the Integration test with @DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD), the first test in the class will fail because SomeServiceInterface is mocked - but the next test will pass because the context has been refreshed already.

Funny thing is:

If I ask Spring to inject SomeServiceInterface in the Integration Test, it will inject a SomeServiceInterface concrete implementation - not a mock!

I have tried many things to sort out that issue:

  1. Programatically override the beans in the context after the component tests are done using the registerBeanDefinition method from the context

  2. Create a TestExecution listener so I could try to manually refresh the context before the execution of an IntegrationTest

  3. Use the same loader for the different contexts....

  4. This story goes on and on.

Does anyone have any idea?

P.S.: I quite understand that adopting Springockito was a dubious idea - but that decision was not made by me and now we have over 500 tests in the project - hence refactoring them all to remove Springockito will be a lenghty task, therefore it is not a viable option ATM.

Zoe
  • 27,060
  • 21
  • 118
  • 148

2 Answers2

0

The @DirtiesContext annotation is handled by the DirtiesContextTestExecutionListener when it's registered with the TestContextManager. With plain vanilla Spring tests, that listener is registered by default. Perhaps Springockito or something else in your test "component test" is doing something that interferes with the default listener registration?

Ryan Stewart
  • 126,015
  • 21
  • 180
  • 199
  • Yes, I know that listener - I did debug the code and the testContext.markContextAsDirty() is called by this very same listener. I played around with listeners and tried to create a customized listener that force the Spring Context to be refreshed before the first **Integration Test** is executed after the **Component Tests** are done. Did not work =( –  Feb 02 '13 at 11:49
0

I suggest to try latest springockito-annotations 1.0.8 with

@DirtiesMocks(classMode = DirtiesMocks.ClassMode.AFTER_CLASS)

See https://bitbucket.org/kubek2k/springockito/wiki/springockito-annotations#!reseting-mocksspies-in-experimental-package-hope-youll-like-it.

Zoe
  • 27,060
  • 21
  • 118
  • 148
Vadzim
  • 24,954
  • 11
  • 143
  • 151