I wanted a way of using my test with dependencies coming from my Spring definition.
The first approach is by requesting the bean from Spring before the tests are being executed:
public class MyDaoImplTest { @BeforeClass public static void setup() { myDao = (MyDaoImpl) TestSpringUtil.getFactory().getBean("myDao"); } }
Notice that you need a specific SpringUtil class if you want (like me) to have a slightly different configuration for your beans under test. In my case, I needed them to point to a test database instance, not to the production instance.
The code was for JUnit 4, of course, but that’s extremely similar in JUnit 3.x:
public class MyDaoImplTest extends TestCase { public void setUp() { myDao = (MyDaoImpl) TestSpringUtil.getFactory().getBean("myDao"); } }
(written from the top of my head)
If you do not want to get the bean manually from Spring, one option is to declare your tests in your Spring configuration. Quite ugly of course: I do not want to burden my configuration with tests (though that can be mitigated by having a separate, additional Spring configuration for test classes).
An alternative is to use the class AbstractDependencyInjectionSpringContextTests (cute name) from Spring. That will allow you declare your dependencies in your test classes and wait for Spring to populate them.
public class MyDaoImplTest extends AbstractDependencyInjectionSpringContextTests { private MyDaoImpl myDao; public void setMyDao(MyDaoImpl myDao) { this.myDao = myDao; } // specifies the Spring configuration to load for this fixture protected String[] getConfigLocations() { // applicationContext-dbaccess-test.xml is the place where access to my test db // is defined and overrides access defined in applicationContext.xml return new String[] { "classpath:com/company/application/applicationContext-dbaccess-test.xml", "classpath:com/company/application/applicationContext.xml" }; } }
The drawback, though, is that you are stuck with JUnit 3.x. The Spring team has not ported their class to JUnit 4.x yet.
Enter Gienah Testing.
Gienah is a very simple tool that let you weave declaratively your test classes with their dependencies:
@RunWith(value = SpringRunner.class) @Configuration(locations = { "classpath:com/company/application/applicationContext-dbaccess-test.xml", "classpath:com/company/application/applicationContext.xml" }) public class MyDaoImplTest { @Dependency private MyDaoImpl myDao; }
That’s it! Clean and easy.
Gienah is still in version E0.3, but seems already very useful. Check out their 5 mins tutorial, it’s well worth it.
A last word: Gienah can handle transactional contexts as well, so that you can test your collections in your unit tests, even if they are lazy loaded. Just add the @Transactional annotation:
@Test @Transactional public void testListEmpty() { assertEquals(0, myDao().getAnObject().getDependentObjectList().size()); }
However, a limitation on that is the name of the transaction manager in your Spring configuration must be exactly “transactionManager”, not “txManager” or anything else. I couldn’t find a way to specify it. This is unfortunate as Spring claims to find the transaction manager whatever its name is. See Testing – Transaction Management:
AbstractTransactionalSpringContextTests depends on a PlatformTransactionManager bean being defined in the application context. The name doesn’t matter, due to the use of autowire by type.
Hi Eric,
Thanks for your comments about Gienah Testing project. Only one thing: As you said, current version E0.3 can’t handle different names for transactionManager attribute, but, you can check out project from SVN to get a working copy with this problem fixed. This fix will be published in E0.4 version.
Next experimental release of gienah-testing (E0.5) is still in progress due to some changes JUnit 4.4 introduced that breaks the way Runners work. I hope version E0.5 will be the last experimental version.
Thanks a lot,
Santiago L. Valdarrama
Gienah-Testing Project Manager
Pingback: ericlefevre » Unitils: a better Gienah?
This is a very useful tool and I’m surely going to use it to test my DAO/service classes!
It is certainly nice to be able to use the JUnit 4 annotations with Spring instead of having to write my own context setup and transaction code, or extending the older Spring unit test class!
(I did run into some trouble with the @Dependency returning some kind of $Proxy object instead of my class. I solved this by adding `proxy-target-class=”true”‘ to my `’ tag. Maybe I should read the manual :-D)
Do we have a way to set autowireMode on srping test cases?
I seems can not find anything in source. I’d like to tyr Gienah if I can change autowireMode
thanks
Hi Gehu,
If you use AbstractDependencyInjectionSpringContextTests, then you get autowire, if you provide the appropriate setters (it will not work for simple properties names). However, you are then stuck with JUnit 3.x.
If you want JUnit 4.x, then last time I checked, you won’t get autowire with Spring directly (this might have changed in the latest version of Spring). Gienah will help you get around this.
Another tool that might be useful in place of Gienah is Unitils.
Pingback: ericlefevre » I am a jealous man