如何在单元测试环境中覆盖Play框架控制器?

Eri*_*rce 5 java unit-testing dependency-injection playframework playframework-2.2

我正在创建一个基本的POST JSON api端点.我想对它进行单元测试,并希望确保我在Play框架中正确地进行测试.到目前为止,我使用Guice进行依赖注入,使用JUnit进行单元测试库.

这是我的控制器代码:

public class NotificationController extends Controller {

  private RabbitQueueService _rabbitQueueService;

  @Inject
  public NotificationController(RabbitQueueService service) {
    _rabbitQueueService = service;
  }

  @BodyParser.Of(BodyParser.Json.class)
  public Result post() {
    ObjectMapper mapper = new ObjectMapper();
    Notification notification;

    try {
      JsonNode notificationJsonNode = Controller.request().body().asJson();
      notification = mapper.readValue(notificationJsonNode.toString(), 
                                      Notification.class);
      _rabbitQueueService.push(notification);
      return Results.created(notificationJsonNode, "UTF-8");

    } catch (JsonParseException e) {
      e.printStackTrace();
    } catch (JsonMappingException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }

    return Results.badRequest();
  }
}
Run Code Online (Sandbox Code Playgroud)

我的RabbitQueueService代码:

public class RabbitQueueService {

  private Channel _channel;
  private Connection _connection;

  public RabbitQueueService() {
      ConnectionFactory factory = new ConnectionFactory();
    factory.setHost(Config.RABBITMQ_HOST);
    try {
      _connection = factory.newConnection();
      _channel = _connection.createChannel();
      _channel.queueDeclare(Config.RABBITMQ_QUEUE, false, false, false, null);
      _channel.exchangeDeclare(Config.RABBITMQ_EXCHANGE, "fanout");
      _channel.queueBind(Config.RABBITMQ_QUEUE, Config.RABBITMQ_EXCHANGE, "");
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  public void push(Notification notification) {
    try {
      _channel.basicPublish(Config.RABBITMQ_EXCHANGE, "", null, notification.getBytes());
        _channel.close();
        _connection.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public void pop() {

  }
}
Run Code Online (Sandbox Code Playgroud)

我的MockQueueService代码:

public class MockQueueService extends RabbitQueueService {

  @Override
  public void push(Notification notification) {
    /* Do nothing because you know... thats what I do */
  }

  @Override
  public void pop() {
    /* Do nothing because you know... thats what I do */
  }
}
Run Code Online (Sandbox Code Playgroud)

最后是我目前的单元测试代码:

public class ApplicationTest {

    @Test
    public void addMessageToQueue() {
      running(fakeApplication(), new Runnable() {
          public void run() {
              FakeRequest request = new FakeRequest("/POST", "/api/v1/notifications");
              Notification notification = new Notification(UUID.randomUUID(), 
                                                           new NotificationType(UUID.randomUUID(), 
                                                                                "Critical"), 
                                                           "Test notification message");
        try {
                  ObjectMapper mapper = new ObjectMapper();
                  String json = mapper.writeValueAsString(notification);
                  JsonNode node;
          node = mapper.readTree(json);
                  request.withJsonBody(node);
        } catch (IOException e) {
          e.printStackTrace();
        }
              route(request);
          }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

当通过播放运行测试我的端点的curl请求时,这一切都正常.我的主要问题是:如何在单元测试中使用MockQueueService?我还没有看到使用fakeApplication()帮助器做到这一点.我可以直接实例化它

NotificationController nc = new NotificationController(new MockQueueService());
nc.post();
Run Code Online (Sandbox Code Playgroud)

但问题是我需要用适当的请求体覆盖播放请求的主体,我我需要一个FakeRequest.

任何帮助,样品或建议都会有所帮助.

UPDATE

我已经发布了一个必要的示例文件的gist示例.特别是我为了让它发挥作用而做的事情:

  • 设置我传递给fakeApplication助手的新GlobalUnitTest文件
  • 将NotificationController更改为单例.这允许我拉入NotificationController实例,这样我就可以检查QueueService计数作为断言的一部分.

Jam*_*mie 1

FakeApplication接受一堆参数,您可以使用它们来注入新服务。您可以使用其中任何一个的组合:

  • 附加插件
  • 附加配置
  • 与全球

它们都允许您指定一些只能在测试期间使用的附加配置。您可以做的另一件事是有一个单独的Global对象仅用于测试,用于创建控制器。当您在路由定义中使用时,该Global对象用于返回控制器实例。@然后,您可以创建一个单独的文件application.test.conf来引用GlobalTest运行时加载的文件play test