Showing posts with label junit. Show all posts
Showing posts with label junit. Show all posts

Wednesday, February 6, 2013

Simple session and request scopes for spring unit tests

I've ran into this several times before and today it happened again. You get a message like this

java.lang.IllegalStateException: No Scope registered for scope ‘session’

when running spring managed unit tests on your spring managed beans.


I remember having created a complex solution the last time for this issue. But today I found this blog entry. What you do is to register
org.springframework.context.support.SimpleThreadScope  
for the session and request scope using the
org.springframework.beans.factory.config.CustomScopeConfigurer 
bean. The technical details are outlined in the blog post, you can read that entry for yourselves. This solution is much more pretty than my old one that you can find in some of my old sources on github. The original idea comes from here, but that blog seems to be borken.

Friday, August 10, 2012

Surefire plugin wont run my JUnit tests!

I spent way to much time on this trivial issue to not write it down. I ran into an issue where my unit tests (JUnit 4) were running fine in Eclipse but not by the maven surefire plugin.

Google served up numerous solutions to my problem but it didn't help me. My problem was much simpler. Eclipse will run any test in any class where the method is annotated with @Test. This does not apply to surefire. If the class is not named Test, surefire will not even look for tests in it. Hence, in maven projects, we should always name test classes that way.

Wednesday, October 28, 2009

Painful unit testing in struts 2

If you plan on doing unit testing and truly decoupled action classes in struts 2 I must recommend you not to use the abstract (but helpful) ActionSupport class in your class hierarchy. Why? Many reasons, here's one.

The ActionSupport class contains some hard coupling which makes unit testing outside of a struts 2 "ActionContext" impossible. Of course, you can set up an ActionContext in the tests setUp() method and you're home free, but it's a heavy and unnecessary fixture. Inheriting the ActionSupport class binds you to this solution in some cases. Amongs others, this field

private final transient TextProvider textProvider =
new TextProviderFactory().createInstance(getClass(), this);

is a pain.
If the ActionContext is not setup, any call to getText(...) will cause a null-pointer exception at this line

ValueStack valueStack = ActionContext.getContext().getValueStack();

for obvious reasons.

This leaves you with three options. either you build up that awful fixture and build fragile tests which all fails in groups and tests much more logic than they should. Or you avoid testing code which touches this stuff. Or you copy the ActionSupport class (watch out for the license!) and set the field to default visibility instead of private final and replace it with a mock in the unit test.

Saturday, September 12, 2009

Decoupling struts actions

Searching Google for struts unit test techniques you find a lot of discussions and blogs on the subject. The only ones I've found are either discussing the StrutsTestCase or how in some other way (manual) setup the entire struts machinery to run unit tests. I have however not found anything about how to test action classes alone.

Testing struts actions with the StrutsTestCase tests much more than just the logic in the action class itself, which is normally what you want to do in a well isolated and simple unit test. I am not interested in whether urls are correctly mapped or request parameters are set on my models by struts. This is something the struts developers do themselves, I assume, and for me it is actually more of an integration test.

So, to my issue. Trying to unit test my actions I ran into a new issue the other day testing an action using the getText(..) method. This particular method, in the end, locates package resources in it's own directory (from the action class) and parent packages until a resource is perhaps finally found. This requires the environment to know about which action class is executing. I've been trying to mock this condition away with combinations of easyMock and the struts bundled mock classes. To no avail.

The problem here is a classic one when you try to unit test. It is because I have extended the bundled ActionSupport (for convenience) and it contains:
private final transient TextProvider textProvider = 
new TextProviderFactory().createInstance(getClass(), this);
private final ValidationAwareSupport validationAware =
new ValidationAwareSupport();

The ValidationAwareSupport is just a datastructure to decrease code size of the validation aware class and has no external dependencies, which makes it a non-issue.
The TextProviderFactory however, is a big issue. Skipping a few details, digging into it, it depends on just about everthing. There are utility methods accessing action context and the valuestack and so forth. Wanting to avoid the execution context, in this case the action context (and possibly more), this should of course be decoupled.

I have already, since long back written my own ActionSupport since I didn't want it to be serializable. And, now decoupling the TextProvider is not very hard. I just add an interceptor that injects the TextProvider into the action during struts invocation. After this I'm free to provide a truly decoupled mock TextProvider in my unit test.

@Override
public String intercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
if (action instanceof TransientActionSupport) {
if (logger.isDebugEnabled()) {
logger.debug("Setting text provider on action");
}
((TransientActionSupport)action).setTextProvider(
new TextProviderFactory().createInstance(
action.getClass(), (LocaleProvider)action));
}
return invocation.invoke();
}

The next step is just to add the interceptor to your default interceptor stack, and you have the same functionality in your webapp as before.