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 224 other followers

  • Sleepless Nights…

    October 2009
    S M T W T F S
  • Blog Stats

    • 1,034,589 hits

Archive for October 28th, 2009

CloudCamp Atlanta tonight

Posted by David Chandler on October 28, 2009

I’m planning to do a short unconference session on securing AppEngine services with gwt-dispatch and unit testing with AppEngine and gwt-dispatch at tonight’s CloudCamp Atlanta.

I’m looking forward to meeting some local AppEngine developers, as I’ve been feeling awfully close to the bleeding edge lately. I routinely find that solutions have been posted on AppEngine forums just eight days ago, and sometimes don’t exist yet. I really need TaskQueue in order to send out emails, which is still experimental in Labs, and would even more like to use deferred.defer (less than two weeks old), but alas, it’s currently only available for Python.

Posted in AppEngine | Leave a Comment »

Writing common test data services for gwt-dispatch with Guice

Posted by David Chandler on October 28, 2009

The way it stands now after my last several posts on unit testing is that each test method in a JUnit TestCase runs its own context, including its own PersistenceManager injected with Guice. Because I’m initializing the AppEngine test environment with LocalDatastoreService.NO_STORAGE_PROPERTY = TRUE, any test data I create in one test is not available to the next test method, even in the same TestCase class. This is typical behavior for JUnit test cases, and generally a good thing as each test should be independent, but it does mean we need a convenient way to create test data. My current strategy is twofold:

  1. Create test data used by all tests in the TestCase setUp() method that runs before each test
  2. Create common test data (used by multiple TestCases) in test data generator services

The first problem to solve is how to get access to a dispatch service and PersistenceManager inside the test data generators. Both are now being injected by Guice as covered in previous posts, so I’ve written a BaseTestDataService that does the Guice magic:

package com.roa.test.service;

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

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.roa.server.guice.ServerModule;
import com.turbomanage.gwt.server.PMF;
import com.turbomanage.gwt.server.guice.DispatchTestModule;

public class BaseTestDataService
	protected static Injector inj = Guice.createInjector(new ServerModule(),
		new DispatchTestModule());;

	protected static StandardDispatchService getService()
		return inj.getInstance(StandardDispatchService.class);

	protected static PMF getPMF()
		return inj.getInstance(PMF.class);

I’m intentionally using a static getPMF() method to make it as simple as possible to use the test data services in a unit test via static methods. Alternatively, I could have used instance methods and constructor injection, but then you’d have to create a new instance of a test data service in each test, which is just that much more code to write… Also, constructor injection is not possible in this case because the TestCases themselves are not instantiated by Guice, so instantiating a new test data service from a test case would not involve Guice, either.

It does not matter that the BaseTestDataService and BaseTest (below) are both calling Guice.createInjector() and thereby creating multiple Guice contexts, each having its own PMF instance. The important thing for these database tests is that they’re all going against one Datastore, not one PersistenceManager.

Here’s a simple test data generator that extends BaseTestDataService and provides a method to add a test user:

package com.roa.test.service;

import com.roa.client.domain.User;
import com.roa.shared.rpc.AddUserAction;
import com.roa.shared.rpc.AddUserResult;

public class UserTestDataService extends BaseTestDataService
	public static User addTestUser() throws Exception
		// Create new user
		User u = new User();
		AddUserResult userResult = (AddUserResult) getService().execute(
			new AddUserAction(u));
		u = userResult.getUser();
		return u;

Note the call to getService() on line 17. Thanks to Guice, test data generator services can invoke gwt-dispatch ActionHandlers the same way as the tests themselves.
Finally, here’s a test case that calls the above service to create a test user in the Datastore:

package com.roa.test;

import java.util.List;

import javax.jdo.Query;

import com.appenginefan.toolkit.unittests.BaseTest;
import com.roa.client.domain.User;
import com.roa.test.service.UserTestDataService;

public class UserTestCase extends BaseTest

	protected void setUp() throws Exception

	public void testUserAdded() throws Exception
		// Run tests here
		Query q = pm.newQuery(User.class, "emailAddress == e");
		q.declareParameters("java.lang.String e");
		List<User> users = (List<com.roa.client.domain.User>) q.execute("test@example.com");
		assertEquals(1, users.size());
		User user = users.get(0);

I should probably show my BaseTest method, too. I’m using AppEngineFan’s BaseTest as discussed in previous posts and modified the setUp() method for Guice injection as follows:

	 * Sets up the App Engine environment.
	protected void setUp() throws Exception
		if (initializer != null)
			throw new UnsupportedOperationException(
				"setup may only be called once!");
		initializer = new TestInitializer(getEnvironmentOrNull());
		Injector inj = Guice.createInjector(new ServerModule(),
			new DispatchTestModule());
		this.testSvc = inj.getInstance(StandardDispatchService.class);
		this.pm = inj.getInstance(PMF.class).getPersistenceManager();

Thanks to Guice, we can now get access to the PersistenceManager and call ActionHandlers via a dispatch test service even from static methods in test data generators. This greatly streamlines unit testing.

Posted in AppEngine, GIN / Guice, Model-View-Presenter | Leave a Comment »

%d bloggers like this: