If you don’t want read my fascinating commentary, you can skip directly to the solution.
Whenever I’m working with Spring, I tend to go through the following pattern:
- Get annoyed at how complicated and/or tedious problem X is.
- Think to myself: “I bet Spring has a way to do this more easily.”
- Glance over the Spring Reference Documentation and determine it is indeed possible. Yes!
- Start implementation using Spring.
- Get frustrated as the amount of Spring code & XML seems to grow exponentially.
- Read the Spring docs again.
- Replace what I did in step 4 & 5 with a few lines of Spring code, since I now actually understand what is going on.
This was the pattern that I went through with a colleague at my client over the past week or so as we were trying to implement set up FitNesse to call a Spring service.
My first thought — surely FitNesse has a way to do this already. Well lookee here … the FitNesse SuiteFixture seems to fit the bill: “Each suite can provide different configuration information, such as selecting a DB or Spring configurations”. Whoops, did I mention that there are no example, and a google search reveals just about nothing.
Next — The spring-fitnesse project seemed to hold some promise… I bailed out when I read the instructions: “Compile the library: Modify ant.properties to match your installation. Then start ant.” Why don’t they just distrubute a compiled library? Maybe we’ll come back to this if nothing else pans out. <nose-in-air>Plus, I’m a maven guy now, so dropping back into ant seems so last year.</nose-in-air>
Over to this blog posting: The Magic Ingredient for FitNesse, Spring … Could this be it? It’s kind of solving a different (more advanced) problem than we were having, namely getting each FIT test to run in a transaction, and rollback any data changes at the end of the test. We didn’t have this need yet, so modifying the actual Fit Server code seemed like overkill.
Finally, we ran across How to wire your FitNesse fixtures with Spring. This seemed to hold the ticket, but something just didn’t jive. I left a question in the comments (which has since been answered, and may indeed also solve the problem), and continued the quest.
By this time, it was clear that the problem was that the FIT fixtures were invoking my POJO Spring service bean outside of the Spring container, and thus none of the Dependency Injection, etc. was taking place. Going back to the Spring docs (see step 6 above
), it became clear that we were overly complicating matters, and that all we needed to do was have the fixture instantiate the Spring container and then get a Bean from it. Thus, the Fixture code ended up as:
public boolean isValid() {
BeanFactory beanFactory =
new ClassPathXmlApplicationContext("classpath:/spring/applicationContext.xml")
.getAutowireCapableBeanFactory();
loginService = (LoginService)beanFactory.getBean("loginService");
loginService.validateUser(username, password);
}
Obviously, a lot of refactoring can go on here, including moving this setup stuff into a base class, making the bean factory static, etc. — this gets us going however!