I have an application developed using JSF, Spring and JDBC Templates.
Now I want to test Bean and DAO classes. But each method of Bean class
uses FacesContext and when I test these types of method?
And DAO classes we extend SimpleJdbcDaoSupport and it is injected from applicationContext using Spring.
So is it suitable to use JUnit to test this kind of application?
Yes and no, and now you see one of the reasons why I always say that the less javax.faces code in a JSF app, the better.
JUnit testing of DataModel and SelectItem constructs isn't really all that beneficial. You can usually get by with constructing collections, JUnit testing those collection-building processes, and take it for granted that JSF will wrap them properly. Those are the only javax.faces objects that a "clean" JSF backing bean would include.
People tend to code a lot more JSF-specific code than they need to. It's much better to inject data into JSF beans than to use the JSF apis to go out and get info. JSF was, in fact designed with that concept in mind - that JSF beans should potentially be usable (and testable) completely outside a web environment.
Of course, in some cases, you really do need data from the URL or other container-related resources. To keep this sort of code independent (and testable), I keep a special JSFUtils class that has service methods that do the actual FacesContext-related (and other non-generic) functions. This can then be replaced with a mock unit for testing.
My JSF apps are almost all based on Spring, and there's no problem using Spring in a JSF Junit test enviroment. You might want to look at dbunit, for example. It can help with stuff like that.
An IDE is no substitute for an Intelligent Developer.
Joined: Feb 24, 2010
Thanks for your immediate reply.
So you mean i can use junit but for that i have to change my existing code.
I have to minimize the use of FacesContext in my back beans. or
I should have set/get method for FacesContext insead of directly using it.
It can solve my problem.
But is there any other solution except this?
Short of re-inventing FacesContext in your own code, no. About the closest you can come is to run your tests in a web framework such as Cactus. But that means all the delays and overhead of running a full web container.
On the whole, however, I think you'll find that projects that are made of generic components that wire together are not only a lot easier to unit-test, they're also a lot easier to maintain. For one thing, they're less subject to this sort of trauma. Not to mention that the more framework-specific code you have scattered around your app, the more it's going to cost if the framework goes through radical changes.
Joined: Feb 24, 2010
Yes, you are right.
I dont have much idea about cactus.
But what do you say about JSFUnit, its an extension of cactus and junit.
And I have tried it and it works fine with my application.
It should. It's designed exactly for that. Thanks for pointing it out - I haven't set up a Cactus test lately and wasn't aware that there were now JSF-specific extensions.
JSFUnit is a good thing to have for pre-release testing, but it and the Cactus test system both set up an actual J2EE container environment. That's good, since that's what production will be running in, but it does take longer to run through than a simple JUnit test.
But there's another reason why I recommend making components that are JUnit-testable. That's because components that don't have framework-specific stuff inside them are a lot easier to adapt into other systems. For example, if you keep your datamodel and data services layers free of web stuff, you'll be in good shape if you get called on to create some offline utilities or ESB apps using that datamodel. The stuff I've got can be copied and used directly without modifications, since only the external wiring changes. That means I don't have to clone, modify, and maintain a separate set of components.
When I need to unit test code that relies on web service calls, faces context objects etc, I tend to use JMock. JMock can be used to mock interfaces (although you can also mock concrete classes - search for ClassImposteriser).
This way you don't have to worry about setting up objects that you're not interested in testing - you simply mock them and tell JMock that a certain method on an object will return a certain result. This gives you the ability to truely 'unit' test the code you're interested in without having to rely on other classes.
This approach is very handy when your code relies on classes that other people are developing. All they need to provide in order for you to unit test your code, are the interfaces. You can then tell JMock how the methods defined on the interface should behave.