Samo
Samo

Reputation: 8240

Unit testing a Play controller using mocks

The title pretty much says it all. I would like to set up a traditional JUnit test to mock a controller's dependencies and run tests against actions.

I've found that I can achieve my goal like this:

public class AccountsControllerTest {
    private controllers.Accounts accountsController;

    @Test
    public void test() {
        running(fakeApplication(), new Runnable() {
            public void run() {
                accountsController = new controllers.Accounts();
                accountsController.setAccountsWorkflow(mock(workflow.Accounts.class));
            }
        });
    }
}

The obvious problem here is that I'm instantiating my class under test and injecting mock dependencies from the test method itself, when I should be doing that in the setup() method. It seems that the setup() method is useless if I'm going to test my controller in a traditional way.

Of course I can test controllers the way Play recommends, but my application is dependent on an external SOAP web service, so I need unit tests to show that our code is working when their servers are down.

So, what's the best way to unit test a Play controller using mocks while still taking advantage of setup() and teardown() methods?

Edit

I realize I'm assuming some knowledge here, so for those who are unaware, controller instantiation in a unit test must be wrapped in a running() function or Play! will throw a runtime exception saying that no application has been started.

Upvotes: 8

Views: 7281

Answers (1)

Zapodot
Zapodot

Reputation: 462

You could accomplish this using Mockito and Play's FakeApplication and setting the static Http.Context variable.

This way you can write the test like all other JUnit test.

Example:

...
import static play.test.Helpers.status;
import play.test.FakeApplication;
import play.test.Helpers;
import play.mvc.Http;
import play.mvc.Result;
...

@RunWith(MockitoJUnitRunner.class)
public class ApplicationTest {

  public static FakeApplication app;

  @Mock
  private Http.Request request;

  @BeforeClass
  public static void startApp() {
      app = Helpers.fakeApplication();
      Helpers.start(app);

  }

  @Before
  public void setUp() throws Exception {
      Map<String, String> flashData = Collections.emptyMap();
      Http.Context context = new Http.Context(request, flashData, flashData);
      Http.Context.current.set(context);
  }

  @Test
  public void testIndex() {
      final Result result = Application.index();
      assertEquals(play.mvc.Http.Status.OK, status(result));
  }

  @AfterClass
  public static void stopApp() {
      Helpers.stop(app);
  }

Upvotes: 1

Related Questions