TurboManage

David Chandler's Journal of Java Web and Mobile Development

  • David M. Chandler


    Web app developer since 1994 and Google Cloud Platform Instructor now residing in Colorado. Besides tech, I enjoy landscape photography and share my work at ColoradoPhoto.gallery.

  • Subscribe

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 228 other followers

  • Sleepless Nights…

    October 2009
    S M T W T F S
     123
    45678910
    11121314151617
    18192021222324
    25262728293031
  • Blog Stats

    • 1,010,175 hits

Archive for October 20th, 2009

How to unit test gwt-dispatch ActionHandlers with Guice

Posted by David Chandler on October 20, 2009

Here’s an easy recipe for running server-side unit tests against your ActionHandlers. Thanks to Guice, you can simply replace the real dispatch servlet with a DispatchTestService that you call from your unit tests. You’ll pass it an Action and get back a Result just the same as you would from the client. Here’s a simple TestCase (note: I’m extending the BaseTest from AppEngineFan that I mentioned in my previous post in order to get access to a test AppEngine environment).

package com.roa.test;

import net.customware.gwt.dispatch.client.standard.StandardDispatchService;

import com.appenginefan.toolkit.unittests.BaseTest;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.roa.client.domain.User;
import com.roa.server.guice.ServerModule;
import com.roa.shared.rpc.AddUserAction;
import com.roa.shared.rpc.AddUserResult;

public class AddUserTestCase extends BaseTest
{
	private StandardDispatchService testSvc;

	@Override
	protected void setUp() throws Exception
	{
		super.setUp();
		Injector inj = Guice.createInjector(new ServerModule(),
			new DispatchTestModule());
		testSvc = inj.getInstance(StandardDispatchService.class);
	}

	public void testAddUser() throws Exception
	{
		// Create new user
		User u = new User();
		u.setEmailAddress("test@example.com");
		u.setFirstName("Test");
		u.setLastName("User");
		u.setGoogleAccountId("testAccountId");
		AddUserResult userResult = (AddUserResult) testSvc.execute(
			new AddUserAction(u));
		u = userResult.getUser();
	}
}

The Guice injector in the setUp method uses our real ServerModule, which maps each Action to its ActionHandler. The DispatchTestModule simply binds the gwt-dispatch StandardDispatchService to a test implementation. Here’s the DispatchTestModule:

package com.roa.test;

import net.customware.gwt.dispatch.client.standard.StandardDispatchService;

import com.google.inject.AbstractModule;
import com.google.inject.Singleton;

public class DispatchTestModule extends AbstractModule
{
	@Override
	protected void configure()
	{
		bind(StandardDispatchService.class).to(DispatchTestService.class).in(
			Singleton.class);
	}
}

And our DispatchTestService:

package com.roa.test;

import net.customware.gwt.dispatch.client.standard.StandardDispatchService;
import net.customware.gwt.dispatch.server.Dispatch;
import net.customware.gwt.dispatch.shared.Action;
import net.customware.gwt.dispatch.shared.Result;

import com.google.inject.Inject;

public class DispatchTestService implements StandardDispatchService
{
	private Dispatch dispatch;

	@Inject
	public DispatchTestService(Dispatch dispatch)
	{
		this.dispatch = dispatch;
	}

	@Override
	public Result execute(Action<?> action) throws Exception
	{
		Result result = dispatch.execute(action);
		return result;
	}
}

Several of my ActionHandlers call the AppEngine UserService, so I’ve modified AppEngineFan’s TestEnvironment class to supply test values:

...
  public String getEmail() {
//    throw new UnsupportedOperationException();
    return "test@example.com";
  }

  public boolean isLoggedIn() {
//    throw new UnsupportedOperationException();
    return true;
  }

  public String getAuthDomain() {
//    throw new UnsupportedOperationException();
    return "test";
  }
...

I’m using the StandardDispatchService in unit tests in place of the AppEngineDispatchService I wrote about in a previous post because there’s no point in passing the extra session ID parameter with each call to dispatch.execute(). This is yet another benefit to using gwt-dispatch: all my service logic resides in ActionHandlers and can therefore be tested without so much as a mock servlet.

To get to the AppEngine Datastore, my ActionHandlers are using a PersistenceManagerFactory singleton that calls JDOHelper.getPersistenceManagerFactory(). Thankfully, this seems to work just fine in the tests, and I haven’t (yet?) had a need to inject different instances of a PersistenceManager in test vs. main code. See the previous post for a reference to the AppEngineFan code that initializes the AppEngine test environment, including Datastore. Note that the AppEngineFan TestInitializer sets the Datastore service NO_STORAGE_PROPERTY to true. This means that each test method in your TestCase starts with an empty Datastore, so each method needs to begin by populating the data it needs for the test.

Posted in AppEngine, Google Web Toolkit | 4 Comments »

 
%d bloggers like this: