Unit tests, mocking and DI in Java

I have recently been investigating dependency injection (DI) and unit testing using mock objects in Java. After browsing advice on Stack Overflow and trying out various frameworks, I have settled on my favourite stack:

  • Dependency Injection: Guice. It was either Guice or Spring, but don’t want / need all the other stuff bundled with Spring. Nice and lightweight, and simple.
  • Unit tests: JUnit. I chose this because Netbeans (my IDE of choice) has extensive integration with JUnit
  • Mocking framework: EasyMock. As the name implies, it’s easy to use nad seems to be popular, and the documentation is clear
  • AtUnit. This is a nice auto-mocker which integrates Guice with EasyMock, meaning much less code needs writing to set up tests with dependency injected mocks

I knew I had a good stack here because my first tests was easy and quick to write, readable and concise, requiring no base classes to write at all. For me, K.I.S.S. always wins - Keep It Simple Stupid! 

After downloading the libraries and adding them to my project, I just needed to write one class:

import static org.easymock.EasyMock.*;
import atunit.AtUnit;
import atunit.Container;
import atunit.Mock;
import atunit.MockFramework;
import atunit.Unit;
import com.google.inject.Inject;
import components.utilities.ISecurityTask;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AtUnit.class)
@Container(Container.Option.GUICE)
@MockFramework(MockFramework.Option.EASYMOCK)
public class StartupTest
{
    @Inject @Unit Startup startup;
    @Mock ISecurityTask mockSecurityTask;

    @Test
    public void testStart() throws Exception
    {
        expect(mockSecurityTask.userIsAuthorised()).andReturn(true);
        replay(mockSecurityTask);
        startup.start();
        verify(mockSecurityTask);
    }
}

In this test I am testing my Startup class, which has a constructor dependency on ISecurityTask, testing to make sure that it calls userIsAuthorised() on ISecurityTask when startup() is called. To achive this I have:

  • Told JUnit to use AtUnit as the test runner with @RunWith
  • Told AtUnit that I am using Guice as theDI container with @container
  • Told AtUnti I am using EasyMock with @MockFramework
  • Mocked my ISecurityTask interface (you just need to annotate it with @mock and AtUnit will create a mock for it when you run your test) to decouple the concree implementation of ScurityTask from my test
  • Declared my Startup class as the unit under test with @Unit
  • Told Guice to inject starup with dependencies with @Inject. This is where the AtUnit magic happens: because I have declared a mock ISecurityTask, the mock will automatically by injected into Startup
  • Set up an expectation on the mock security task for a call to its userIsAuthorised() method
  • Called startup() on the Statrup class

Now I just need to right-click the test (or a test suite which includes the test) in NetBeans, and hit ‘Run’. I’ll look into running them using Ant later!

posted 2 years ago