Local Unit Testing for Java

Unit testing allows you to check the quality of your code after you've written it, but you can also use unit testing to improve your development process as you go along. Instead of writing tests after you finish developing your application, consider writing the tests as you go. This helps you design small, maintainable, reusable units of code. It also makes it easier for you to test your code thoroughly and quickly.

When you do local unit testing, you run tests that stay inside your own development environment without involving remote components. App Engine provides testing utilities that use local implementations of datastore and other App Engine services. This means you can exercise your code's use of these services locally, without deploying your code to App Engine, by using service stubs.

A service stub is a method that simulates the behavior of the service. For example, the datastore service stub shown in Writing Datastore and Memcache Tests allows you to test your datastore code without making any requests to the real datastore. Any entity stored during a datastore unit test is held in memory, not in the datastore, and is deleted after the test run. You can run small, fast tests without any dependency on datastore itself.

This document provides some information about setting up a testing framework, then describes how to write unit tests against several local App Engine services.

  1. Setting up a testing framework
  2. Introducing the Java testing utilities
  3. Writing Datastore and memcache tests
  4. Writing High Replication Datastore tests
  5. Writing task queue tests
  6. Writing deferred task tests
  7. Writing local service capabilities tests
  8. Writing tests for other services
  9. Writing tests with authentication expectations

Setting up a testing framework

Even though the SDK's testing utilities are not tied to any specific framework, we'll use JUnit for our examples so you have something concrete and complete to work from. Before you begin writing tests you'll need to add the appropriate JUnit 4 JAR to your testing classpath. Once that's done you're ready to write a very simple JUnit test.

import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class MyFirstTest {
  public void testAddition() {
    assertEquals(4, 2 + 2);

If you're running Eclipse 3.5, select the source file of the test to run. Select the Run menu > Run As > JUnit Test. The results of the test appear in the Console window.

For information on running your tests with Apache Ant, please read the Ant JUnit Task documentation.

Introducing the Java testing utilities

MyFirstTest demonstrates the simplest possible test setup, and for tests that have no dependency on App Engine APIs or local service implementations, you may not need anything more. However, if your tests or code under test have these dependencies, add the following JAR files to your testing classpath:

  • ${SDK_ROOT}/lib/impl/appengine-api.jar
  • ${SDK_ROOT}/lib/impl/appengine-api-labs.jar
  • ${SDK_ROOT}/lib/impl/appengine-api-stubs.jar
  • ${SDK_ROOT}/lib/appengine-tools-api.jar

These JARs make the runtime APIs and the local implementations of those APIs available to your tests.

App Engine services expect a number of things from their execution environment, and setting these things up involves a fair amount of boilerplate code. Rather than set it up yourself, you can use the utilities in the com.google.appengine.tools.development.testing package. To use this package, add the following JAR file to your testing classpath:

  • ${SDK_ROOT}/lib/testing/appengine-testing.jar

Take a minute to browse the javadoc for the com.google.appengine.tools.development.testing package. The most important class in this package is LocalServiceTestHelper, which handles all of the necessary environment setup and gives you a top-level point of configuration for all the local services you might want to access in your tests.

To write a test that accesses a specific local service:

  • Create an instance of LocalServiceTestHelper with a LocalServiceTestConfig implementation for that specific local service.
  • Call setUp() on your LocalServiceTestHelper instance before each test and tearDown() after each test.

Writing Datastore and memcache tests

The following example tests the use of the datastore service.

import static com.google.appengine.api.datastore.FetchOptions.Builder.withLimit;
import static org.junit.Assert.assertEquals;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class LocalDatastoreTest {

  private final LocalServiceTestHelper helper =
      new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());

  public void setUp() {

  public void tearDown() {

  // Run this test twice to prove we're not leaking any state across tests.
  private void doTest() {
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
    assertEquals(0, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
    ds.put(new Entity("yam"));
    ds.put(new Entity("yam"));
    assertEquals(2, ds.prepare(new Query("yam")).countEntities(withLimit(10)));

  public void testInsert1() {

  public void testInsert2() {

In this example, LocalServiceTestHelper sets up and tears down the parts of the execution environment that are common to all local services, and LocalDatastoreServiceTestConfig sets up and tears down the parts of the execution environment that are specific to the local datastore service. If you read the javadoc you'll learn that this involves configuring the local datastore service to keep all data in memory (as opposed to flushing to disk at regular intervals) and wiping out all in-memory data at the end of every test. This is just the default behavior for a datastore test, and if this behavior isn't what you want you can change it.

Changing the example to access memcache instead of datastore

To create a test that accesses the local memcache service, you can use the code that is shown above, with a few small changes.

Instead of importing classes related to datastore, import those related to memcache. You still need to import LocalServiceTestHelper.

import com.google.appengine.api.memcache.MemcacheService;
import com.google.appengine.api.memcache.MemcacheServiceFactory;
import com.google.appengine.tools.development.testing.LocalMemcacheServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;

Change the name of the class that you are creating, and change the instance of LocalServiceTestHelper, so that they are specific to memcache.

public class LocalMemcacheTest {

  private final LocalServiceTestHelper helper =
      new LocalServiceTestHelper(new LocalMemcacheServiceTestConfig());

And finally, change the way you actually run the test so that it is relevant to memcache.

private void doTest() {
  MemcacheService ms = MemcacheServiceFactory.getMemcacheService();
  ms.put("yar", "foo");

As in the datastore example, the LocalServiceTestHelper and the service-specific LocalServiceTestConfig (in this case LocalMemcacheServiceTestConfig) manage the execution environment.

Writing High Replication Datastore tests

If your app uses the High Replication Datastore (HRD), you may want to write tests that verify your application's behavior in the face of eventual consistency. LocalDatastoreServiceTestConfig exposes options that make this easy: