views:

220

answers:

4

We have a Spring + Ibatis based J2EE app. I planned to wrap around our DAO's (which call iBatis templates ...by getting spring beans) with test cases. I don't have much experience with JUnit so I thought that simply making an object of my DAO and then calling one of the methods will work. But wrong I was, turns out that the whole J2EE app runs on appserver (container) but obviously the JUnit test cases are outside the container. So, in my test case, when I make object of the dao and call a method...it fails on a line like this which is in my DAO method

ApplicationInitializer.getApplicationContext().getBean("myMapclientBean");

So I went on a Google hunt...came across some posts and following the tubes I ended up on Spring's 4 day training course.

Wanted to get your guys opinion on what do you think about this course? Is it valuable for the price? And can a person learn this stuff on their own too? By following couple of books? (Maybe not in 4 days but, say, over a month).

oh, and I'm still not able to Unit tests these DAO's...>_<

+3  A: 

I took the Core Spring course about a year and half ago. The syllabus apparently changed a little bit since then, though it's still very similar. The instructor was very competent. I was working with Spring prior to taking this course, but in the class I feel like I learned how to do things even better.

I think you can probably get all of the raw information out of books, Spring's online documentation, and the source code itself, but what the class does is connect everything together and teach best practices. That is, not just "how" but also "why" and "when" you should use such-and-such feature. This is why I felt like my skills improved.

The instructor was happy to answer questions about specific, real-world issues beyond the classwork. So it would be a good idea to come armed with questions.

The course isn't cheap. Whether it's worth it depends on whether you do well with classrooms versus self-teaching and utilizing online communities and peers to get that feel of best practices that books just don't offer. Also, keep in mind that Spring is constantly evolving. Although you can get a good foundation from the class, you'll still have to adapt to new features down the road (or take another class).

Jeff
Also took the course and I agree with everything @Jeff said. IMO it was well worth it.
Alex Beardsley
thanks guys. thats helpful. I'll ask for my small company and see if they are willing....or i'll start lurking around jobs.SO :). Since you guys took training can you tell me how Testcases will work if the J2EE app works inside a container (app server). I mean all the datasources and stuff are on the app server...so how will jUnit work when your DAO's are getting datasources from the appserver?
Drake
Your description sounds more like an integration test than a unit test... but that seems to always be the case when testing DAOs and databases. You may want to look at the AbstractTransactionalDataSourceSpringContextTests class. This might also come in handy for you: http://iamjosh.wordpress.com/2007/12/11/unit-testing-dao-classes-with-junit-spring/
Jeff
A: 

To solve the problem at hand:

When using Spring, your beans shouldn't really go out to the ApplicationContext and ask for the beans they need - they should provide setters (or constructors) so that the dependencies can be injected.

It sounds like whomever designed these classes did the opposite of dependency injection.

matt b
under the hood...the context is coming like this springContext = WebApplicationContextUtils .getWebApplicationContext(event.getServletContext());could you please provide a little sample of how you think they should be so that Junit test cases would be able to use these beans outside of the container?
Drake
The Spring MVC tutorial, even though it's specifically for the MVC framework, is an excellent intro to Spring, IMO. http://static.springframework.org/docs/Spring-MVC-step-by-step/ Dependency Injection means that a class is *given* it's dependencies, not that it goes out and finds them.
matt b
+1  A: 

In answer to the second part of the question (I have not had experience of the spring course so can't comment).

You can make use of a defined application context from within Junit tests and then instantiate the DAO's as you would from within the server container either through having your test case extend AbstractTransactionalDataSourceSpringContextTests if you are using Junit 3.8 or older.

If you are using later Junit versions (4+) you can use Spring TestContext framework and annotations.

Both explained far better than i can here from Spring and on this annotations RefCard

TomY
-1 - AbstractTransactionalDataSourceSpringContextTests is an abortion. So are much of the Spring provided test case extensions. AbstractSingleSpringContextTests is where you should stop using them - they get more and more awful after that point.
MetroidFan2002
Its sure an opinion. Just showing the options, the guy asking the question can then find his own way to get things done.
TomY
I've used the AbstractTransactionalDataSourceSpringContextTests route. works for me. I've instantiated junits for the remoting project we have at work and this forms the basis of our junit tests. via<code>public class TestBase extends AbstractDependencyInjectionSpringContextTests</code>
jeff porter
A: 

I've used the AbstractTransactionalDataSourceSpringContextTests route. works for me. I've instantiated junits for the remoting project we have at work and this forms the basis of our junit tests. via

import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
public class TestBase extends AbstractDependencyInjectionSpringContextTests
{
  protected String[] getConfigLocations()
  {
    return new String[] { "classpath:conf/dataAccessContext.xml",     "classpath:conf/applicationContext-domain.xml",
    "classpath:conf/applicationContext-service.xml", "classpath:conf/applicationContext-dao.xml" };
  }

  protected Object getBeanToTest(String beanName)
  {
    return applicationContext.getBean(beanName);
  }

  protected Object getBeanToTest(Class clazz)
  {
    return applicationContext.getBean(clazz.getName());
  }

}
jeff porter