On Monday, Oct 28, 2002, at 16:19 Europe/London, Patrick Lightbody wrote:

I like the StackableActionFactory, I'll make sure it gets in to XWork at
least.
Thanks.

But what is the XAwareActionFactoryProxy exactly for? I do tons of unit
testing with my actions (using GenericDispatcher as a launching place) and
I've not needed something like this.
The need for something like this arose from a conversation I was having about how to unit test webwork actions without needing to fire up a complete app server --- a process that takes an age on my machine, and therefore acts a significant deterrent to doing "proper" TDD.

The suggested solution was to make use of Mock Objects, which can be passed into the Action at test time. So you end up with a chunk of code that looks a little like:

public void testNoUsernamePassedIntoClass() {
MockUser user = new MockUser();
user.setExpectedSetUsernameCalls( 0 );

UserEditAction action = new UserEditAction();
action.setUser( user ); // Action is UserAware
action.setNewUsername( null ); // User name has not been filled in

String result = action.execute();
assertEquals( Action.SUCCESS, result );
user.verify();
}

Obviously, the User class has to be tested elsewhere, but that's another problem entirely. Using a style like this, I can run a whole test suite in seconds, without having to deploy the app once or go through the shenanigans of having a properly configured installation of WW[1].

The question remains, however, as to how to get WW to pass in the state. As hinted in the snippet of code, one way would be to create an interface such as UserAware:

public interface UserAware {
void setUser( User aUser );
}

And a matching factory to go with it:

public class UserAwareFactoryProxy {
public static void setUser( Action anAction ) {
ActionContext context = ActionContext.getContext();
User user = (User)context.getSession().get("currentUser");
((UserAware)action).setUser( user );
}
}

It would be possible to simply append "User" to the list of factories that StackableActionFactory gets to use, but this can become inefficient --- not every Action is UserAware --- and doesn't allow one to be properly Lazy[2] Instead, the developer has only to state in webwork.properties what packages to search through, and action.setUser() will be called automagically by XAwareActionFactoryProxy if (and only if) the action happens to be UserAware, without requiring a potentially enormous custom action factory class, and with only a tiny amount of overhead once the first invocation is done.

I know that I'm not the only one who thinks like this. Just today, Darran Hobbs posted:

"I suppose I prefer the passive bean like approach where state is passed in
from outside, leaving my implementations unaware of anything other than
their own state and the interfaces they implement. Its a personal
style thing I guess. I've been IOC indoctrinated :)"

If I can do the same "out of container" testing using the GenericDispatcher, I would happily do that, especially if it was as fast as the method described above, though I am unsure how to set things up. Do you have any examples that I could see?

Also, the *Aware interfaces have been deprecated.
I had noticed the warnings when I compiled webwork from source. What's the preferred idiom for passing data into an Action now?

Regards,

Simon

[1] Obviously, the acceptance tests ensure that WW is configured properly when the app is deployed.
[2] In the Perl-ish sense :)


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
Opensymphony-webwork mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/opensymphony-webwork


Reply via email to