单元测试 - Java Play 2.42.5

助手和假应用程序

Class Helpers 用于单元测试。它模仿 Play 应用程序,伪造 HTTP 请求和响应,会话,cookie - 所有测试可能需要的东西。测试中的控制器应该在 Play 应用程序的上下文中执行。的助手方法 fakeApplication 提供了一种用于运行测试的应用程序。为了使用 HelpersfakeApplication ,测试类应该派生自 WithApplication

应使用以下 Helpers API:

Helpers.running(Application application, final Runnable block);
Helpers.fakeApplication();

使用助手进行测试如下所示:

public class TestController extends WithApplication {
 @Test  
 public void testSomething() {  
     Helpers.running(Helpers.fakeApplication(), () -> {  
         // put test stuff  
         // put asserts  
     });
 }  
}  

为 Helpers 方法添加 import 语句使代码更紧凑:

 import static play.test.Helpers.fakeApplication;
 import static play.test.Helpers.running;
 ...
 @Test  
 public void testSomething() {  
      running(fakeApplication(), () -> {  
           // put test stuff  
           // put asserts  
       });
 }

}

测试控制器

让我们调用一个控制器方法,该方法作为路由方法绑定到路由中的特定 URL。调用路由方法称为控制器操作,并具有 Java 类型调用。Play 为每个动作构建所谓的反向路径。调用反向路由会创建适当的 Call 对象。该反向路由机制用于测试控制器。 **** **** **** ** **

要从 test 调用控制器操作,应使用以下 Helpers API:

Result result = Helpers.route(Helpers.fakeRequest(Call action));

控制器测试示例

  1. 路线
GET /conference/:confId    controllers.ConferenceController.getConfId(confId: String)  
POST /conference/:confId/participant controllers.ConferenceController.addParticipant(confId:String) 
  1. 生成的反向路线:

    controllers.routes.ConferenceController.getConfId(conferenceId) 
    controllers.routes.ConferenceController.addParticipant(conferenceId)
    
  2. 方法 getConfId 绑定到 GET ,并且不在请求中接收正文。可以调用它来进行测试:

    Result result = Helpers.route(Helpers.fakeRequest(controllers.routes.ConferenceController.getConfId(conferenceId)));
    
  3. 该方法 addParticipant 势必 POST 。它希望在请求中收到一个正文。它在测试中的调用应该像这样:

    ParticipantDetails inputData = DataSimulator.createParticipantDetails();
    Call action = controllers.routes.ConferenceController.addParticipant(conferenceId);
    Result result = route(Helpers.fakeRequest(action).bodyJson(Json.toJson(inputData));
    

嘲笑 PowerMock

要启用模拟,测试类应注释如下:

@RunWith(PowerMockRunner.class)
@PowerMockIgnore({"javax.management.*", "javax.crypto.*"})
public class TestController extends WithApplication {
....

模拟控制器动作

使用 RequestBuilder 模拟控制器调用 :

RequestBuilder fakeRequest = Helpers.fakeRequest(action); 

对于上面的 addParticipant,操作被模拟为:

RequestBuilder mockActionRequest = Helpers.fakeRequest(controllers.routes.ConferenceController.addParticipant(conferenceId)); 

要调用控制器方法:

Result result = Helpers.route(mockActionRequest);

整个测试:

@Test
public void testLoginOK() {
 running(fakeApplication(), () -> {
      ///*whatever mocking*/Mockito.when(...).thenReturn(...);
      RequestBuilder mockActionRequest = Helpers.fakeRequest(
           controllers.routes.LoginController.loginAdmin());
      Result result = route(mockActionRequest);
      assertEquals(OK, result.status());
 });
}

使用 JSON 正文模拟动作

我们假设输入是 T 类型的对象。动作请求模拟可以以几种方式完成。

选项 1:

public static <T> RequestBuilder fakeRequestWithJson(T input, String method, String url) {  
  JsonNode jsonNode = Json.toJson(input);  
  RequestBuilder fakeRequest = Helpers.fakeRequest(method, url).bodyJson(jsonNode);  
  System.out.println("Created fakeRequest="+fakeRequest +", body="+fakeRequest.body().asJson());  
  return fakeRequest;  
}  

选项 2:

public static <T> RequestBuilder fakeActionRequestWithJson(Call action, T input) {  
  JsonNode jsonNode = Json.toJson(input);  
  RequestBuilder fakeRequest = Helpers.fakeRequest(action).bodyJson(jsonNode);  
  System.out.println("Created fakeRequest="+fakeRequest +", body="+fakeRequest.body().asJson());  
  return fakeRequest;  
} 

使用基本身份验证标头模拟操作

动作请求嘲笑:

public static final String BASIC_AUTH_VALUE = "dummy@com.com:12345";
public static RequestBuilder fakeActionRequestWithBaseAuthHeader(Call action) {
  String encoded = Base64.getEncoder().encodeToString(BASIC_AUTH_VALUE.getBytes());
  RequestBuilder fakeRequest = Helpers.fakeRequest(action).header(Http.HeaderNames.AUTHORIZATION,
                                             "Basic " + encoded);
  System.out.println("Created fakeRequest="+fakeRequest.toString() );
  return fakeRequest;
}

用会话嘲笑动作

动作请求嘲笑:

public static final String FAKE_SESSION_ID = "12345";
public static RequestBuilder fakeActionRequestWithSession(Call action) {
  RequestBuilder fakeRequest = RequestBuilder fakeRequest = Helpers.fakeRequest(action).session("sessionId", FAKE_SESSION_ID);
  System.out.println("Created fakeRequest="+fakeRequest.toString() );
  return fakeRequest;
}

Play Session 类只是 HashMap <String,String> 的扩展。它可能会被简单的代码嘲笑:

public static Http.Session fakeSession() {  
  return new Http.Session(new HashMap<String, String>());  
}