How do I avoid initializing SpringJUnit4ClassRunner beans before they mock JMockit?

I have a JUnit test class like this:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration( locations = { "beanDefinitions.xml"})
public class MyTest {

    @Mocked private SomeDependency usedInSpringContext;

    @Test public void letsTest() {
        ...
    }
}

      

The problem is that the Spring runner loads its beans before JMockit has a chance to mock them. How to avoid this? These are JMockit 1.0 and Spring 3.07. I would prefer that my beanDefinitions.xml not change.

The code under test is deprecated. It contains a lot of hardcoded Spring dependencies that I cannot get rid of. So the first step is mocking.

+3


source to share


2 answers


You can use a custom FactoryBean.

This is explained in this blog post . And here's a sample code.



It uses either easymock or Mockito. But I'm sure you can port this to JMockit easily.

EDIT: I forgot that you don't want your beanDefinitions.xml to be modified. But my proposal includes this modification.

+2


source


One of the great things about Spring and Dependency Injection in general is that your classes don't clutter up your code to satisfy their dependencies. They just sit and wait for someone else to fill in the collaborating objects. Thus, it is assumed that it is trivial to include mock objects.

// no Spring runner or context configuration
public class FooTest {
    Foo foo;

    @Before
    public void setup() {
        foo = new Foo();
        foo.setDependency(mock(dependency)); // details depend on mocking framework
    }
}

      

With this approach, you are not using autowire or otherwise injecting the object under test, at least if you intend to reconfigure it by specifying it in mock-workers. If the code under test has a lot of dependencies, you can complete a ton of setup code, but that's okay.

Admittedly, some things (like databases) are hard to mock, so you need a different testing approach to check that your SQL queries (for example) do what you meant. It starts with a separate bean definition file containing something like:

<jdbc:embeded-database id="datasource"/>

      



See http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/testing.html for details .

The tricky part is that if you haven't written Junit tests yet, you might be in a situation where every bean seems to depend on every other bean. Thus, the "unit" you are trying to test is not a single class, but a bunch of related classes. In this case, I suggest splitting the bean definition file into smaller parts and then writing unit tests for each part.

With this approach, you can let Spring plug in the code under test because the Spring configuration is part of the device. The unit test code is still mocking and plugging in external dependencies on that device.

If you insist on making full use of your real beanDefinitions.xml, then you are writing integration tests, not unit tests.

0


source







All Articles