Quantcast

Sunday, October 26, 2008

Integrating Google Guice into JUnit4 tests

You can integrate Guice into your JUnit 4 tests with three simple steps:

  1. Add the following class to your classpath:
    package com.google.inject.junit;
    
    import com.google.inject.Guice;
    import com.google.inject.Injector;
    import com.google.inject.Module;
    import java.util.List;
    import org.junit.runners.BlockJUnit4ClassRunner;
    import org.junit.runners.model.InitializationError;
    
    /**
     * Uses Guice to inject JUnit4 tests.
     *
     * @author Gili Tzabari
     */
    public class GuiceTestRunner extends BlockJUnit4ClassRunner
    {
      private final Injector injector;
    
      /**
       * Creates a new GuiceTestRunner.
       *
       * @param classToRun the test class to run
       * @param modules the Guice modules
       * @throws InitializationError if the test class is malformed
       */
      public GuiceTestRunner(final Class<?> classToRun, Module... modules) throws InitializationError
      {
        super(classToRun);
        this.injector = Guice.createInjector(modules);
      }
    
      @Override
      public Object createTest()
      {
        return injector.getInstance(getTestClass().getJavaClass());
      }
    
      @Override
      protected void validateZeroArgConstructor(List<Throwable> errors)
      {
        // Guice can inject constructors with parameters so we don't want this method to trigger an error
      }
    
      /**
       * Returns the Guice injector.
       *
       * @return the Guice injector
       */
      protected Injector getInjector()
      {
        return injector;
      }
    }

  2. Customize GuiceTestRunner for your specific project by subclassing it. For example:
    package myproject;
    
    import com.google.inject.junit.GuiceTestRunner;
    import com.wideplay.warp.persist.PersistenceService;
    import myproject.GuiceModule;
    import org.junit.runners.model.InitializationError;
    
    /**
     * JUnit4 runner customized for our Guice module.
     *
     * @author Gili Tzabari
     */
    public class GuiceIntegration extends GuiceTestRunner
    {
      /**
       * Creates a new GuiceIntegration.
       *
       * @param classToRun the test class to run
       * @throws InitializationError if the test class is malformed
       */
      public GuiceIntegration(Class classToRun) throws InitializationError
      {
        super(classToRun, new GuiceModule());
      }
    }

  3. Add @RunWith to all your JUnit test classes. For example:

    @RunWith(GuiceIntegration.class)
    public class MyTest
    {
      @Inject
      public MyTest(SomeDependency foo)
      {
        ...
      }
    }

That's it! Guice will now inject your test classes.

EDIT: I'm a convert :) I now use AtUnit to integrate Guice into JUnit.

Saturday, October 18, 2008

RESTful Dynamic Forms

One of the key characteristics of RESTful web services is (application) "statelessness". That is, all application state should be stored on the client-end and send over with every request.

Sometimes clients are asked to manipulate forms dynamically, adding or removing elements, before submitting it to the server. Typically the client uses "sessionId" to manipulate the page across multiple requests.

If you take a step back, however, you will realize that this application state doesn't belong on the server at all. The server doesn't really care about the intermediate page states, which is why it doesn't persist them to the database in the first place. It only cares about the initial page state (which it sends to the client) and the final page state (which it saves to the database). The server manipulates the page state on behalf of the client because it's easier to implement business logic in modern programming languages than it is to implement them in Javascript on the client. Ideally the client should download the page, manipulate it on its end, and submit the result to the server.