Play framework 2.5.x: IllegalStateException: Attempted to call materialize() after the ActorMaterializer has been shut down

Viewed 663

The intention of the Play server is to act as an intermediate service to another system, where the end-users access a small portion of functionality in a web browser on their smartphone.

The service functions as supposed to when connected to the real system. But, I want to have unit tests in a blackbox fashion. Testing the functionality from start to end. To avoid relying on the real system, where values change every day, I wanted to use the same approach as described in Testing web service clients and combine it with the route testing as shown in the example test from the play-java-seed, shown here for convenience:

public class HomeControllerTest extends WithApplication {

    @Override
    protected Application provideApplication() {
        return new GuiceApplicationBuilder().build();
    }

    @Test
    public void testIndex() {
        Http.RequestBuilder request = new Http.RequestBuilder()
                .method(GET)
                .uri("/");

        Result result = route(app, request);
        assertEquals(OK, result.status());
    }
}

My test code then looks as follows:

package controllers;

import java.util.*;

import org.junit.*;
import static org.junit.Assert.*;

import play.Application;
import play.inject.guice.GuiceApplicationBuilder;
import play.mvc.Result;
import play.mvc.Http.RequestBuilder;
import play.routing.*;
import play.server.Server;
import play.test.WithApplication;
import static play.mvc.Http.Status.*;
import static play.mvc.Results.*;
import static play.test.Helpers.*;

public class ApplicationControllerTest extends WithApplication {
  static int FAKE_SERVICE_PORT = 7070;
  Server server;

  @Override
  protected Application provideApplication() {
    return new GuiceApplicationBuilder()
      .configure("externalSystem.port", FAKE_SERVICE_PORT)
      .configure("externalSystem.host", "localhost")
      .build();
  }

  @Before
  public void setup() {
    Router router = new RoutingDsl()
      .GET("/b/1/").routeTo(() ->
        // Request for branch information
        ok().sendResource("externalSystem/getBranch.json")
      )
      .GET("/b/1/a/19033/").routeTo(() ->
        // Request generating an already arrived appointment
        ok().sendResource("externalSystem/arrivedAppointment.json")
      )
      .GET("/b/1/a/19962/").routeTo(() ->
        // Request generating a newly created appointment
        ok().sendResource("externalSystem/createdAppointment.json")
      )
      .build();
    server = Server.forRouter(router, FAKE_SERVICE_PORT);
  }

  @After
  public void tearDown() throws Exception {
    server.stop();
  }

  @Test
  public void AppCtrl() throws Exception {
    // // These values are defined in the json files
    String customerName = "Test User";
    String branchName = "Test Branch";

    RequestBuilder request = new RequestBuilder().method(GET).uri("/1/19962");

    Result result = route(app, request);
    assertEquals(OK, result.status());
    assertTrue(contentAsString(result).contains(customerName));
    assertTrue(contentAsString(result).contains(branchName));
  }
}

However running this test with sbt test produces an IllegalStateException:

[error] Test controllers.ApplicationControllerTest.AppCtrl failed: java.lang.IllegalStateException: Attempted to call materialize() after the ActorMaterializer has been shut down., took 4.165 sec
[error]     at akka.stream.impl.ActorMaterializerImpl.materialize(ActorMaterializerImpl.scala:164)
[error]     at akka.stream.impl.ActorMaterializerImpl.materialize(ActorMaterializerImpl.scala:146)
[error]     at akka.stream.scaladsl.RunnableGraph.run(Flow.scala:350)
[error]     at play.api.libs.streams.DoneAccumulator.run(Accumulator.scala:161)
[error]     at play.api.test.EssentialActionCaller$class.call(Helpers.scala:225)
[error]     at play.api.test.Helpers$.call(Helpers.scala:382)
[error]     at play.api.test.RouteInvokers$class.route(Helpers.scala:247)
[error]     at play.api.test.Helpers$.route(Helpers.scala:382)
[error]     at play.api.test.RouteInvokers$class.jRoute(Helpers.scala:234)
[error]     at play.api.test.Helpers$.jRoute(Helpers.scala:382)
[error]     at play.api.test.Helpers.jRoute(Helpers.scala)
[error]     at play.test.Helpers.route(Helpers.java:360)
[error]     at play.test.Helpers.route(Helpers.java:355)
[error]     at controllers.ApplicationControllerTest.AppCtrl(ApplicationControllerTest.java:63)
[error]     ...
[error] Failed: Total 1, Failed 1, Errors 0, Passed 0
[error] Failed tests:
[error]         controllers.ApplicationControllerTest
[error] (test:test) sbt.TestsFailedException: Tests unsuccessful

I guess I could implement a completely standalone server to mock the service, but I would much rather not have the tests rely on a separate server.

So my question is this: Has anyone done someting similar with Play, and in that case what have I done wrong?

0 Answers
Related