文件

§測試您的應用程式

為您的應用程式撰寫測試可能是一個複雜的過程。Play 支援 JUnit,並提供輔助程式和應用程式程式碼片段,讓測試您的應用程式變得盡可能容易。

§概觀

測試的位置在「test」資料夾中。在測試資料夾中建立了兩個範例測試檔案,可用作範本。

您可以在 sbt 主控台中執行測試。

Play 中的測試基於 sbt,完整的說明可在 測試文件 中取得。

§使用 JUnit

測試 Play 應用程式的預設方式是使用 JUnit

import static org.junit.Assert.*;

import org.junit.Test;

public class SimpleTest {

  @Test
  public void testSum() {
    int a = 1 + 1;
    assertEquals(2, a);
  }

  @Test
  public void testString() {
    String str = "Hello world";
    assertFalse(str.isEmpty());
  }
}

注意:每次執行 testtest-only 時,都會分岔一個新程序。新程序會使用預設的 JVM 設定。自訂設定可以新增到 build.sbt。例如

Test / javaOptions ++= Seq(
  "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=9998",
  "-Xms512M",
  "-Xmx1536M",
  "-Xss1M"
)

§斷言和比對器

有些開發人員偏好以比 JUnit 斷言更流暢的風格撰寫他們的斷言。為了方便起見,已包含其他斷言風格的熱門函式庫。

Hamcrest 比對器

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class HamcrestTest {

  @Test
  public void testString() {
    String str = "good";
    assertThat(str, allOf(equalTo("good"), startsWith("goo")));
  }
}

§模擬

模擬用於隔離單元測試與外部依賴項。例如,如果您的受測類別依賴於外部資料存取類別,您可以模擬此類別以提供受控資料,並消除對外部資料資源的需求。

Mockito 函式庫是 Java 中一個熱門的模擬架構。若要在您的測試中使用它,請在您的 build.sbt 檔案中新增對 mockito-core 人工製品的依賴項。例如

libraryDependencies += "org.mockito" % "mockito-core" % "2.10.0" % "test"

您可以在 這裡 找到 mockito-core 的目前版本號碼。

使用 Mockito,您可以像這樣模擬類別或介面

import static org.mockito.Mockito.*;
// Create and train mock
List<String> mockedList = mock(List.class);
when(mockedList.get(0)).thenReturn("first");

// check value
assertEquals("first", mockedList.get(0));

// verify interaction
verify(mockedList).get(0);

§單元測試模型

假設我們有下列資料模型

public class User {
  private Integer id;
  private String name;

  public User(final Integer id, final String name) {
    this.id = id;
    this.name = name;
  }
}

public class Role {
  private String name;

  public Role(final String name) {
    this.name = name;
  }
}

某些資料存取函式庫,例如 Ebean 允許您使用靜態方法將資料存取邏輯直接放入模型類別中。這可能會讓模擬資料相依性變得棘手。

可測試性的常見方法是讓模型與資料庫保持孤立,並盡可能包含邏輯,並將資料庫存取抽象化到儲存庫介面之後。

public interface UserRepository {
  public Set<Role> findUserRoles(User user);
}

public class UserRepositoryEbean implements UserRepository {
  @Override
  public Set<Role> findUserRoles(User user) {
    // Get roles from DB
     ...
  }
}

然後使用包含儲存庫的服務與模型互動

public class UserService {
  private final UserRepository userRepository;

  public UserService(final UserRepository userRepository) {
    this.userRepository = userRepository;
  }

  public boolean isAdmin(final User user) {
    final Set<Role> roles = userRepository.findUserRoles(user);
    for (Role role : roles) {
      if (role.name.equals("ADMIN")) return true;
    }
    return false;
  }
}

這樣一來,UserService.isAdmin 方法就可以透過模擬 UserRepository 相依性來進行測試

@Test
public void testIsAdmin() {

  // Create and train mock repository
  UserRepository repositoryMock = mock(UserRepository.class);
  Set<Role> roles = new HashSet<Role>();
  roles.add(new Role("ADMIN"));
  when(repositoryMock.findUserRoles(any(User.class))).thenReturn(roles);

  // Test Service
  UserService userService = new UserService(repositoryMock);
  User user = new User(1, "Johnny Utah");
  assertTrue(userService.isAdmin(user));
  verify(repositoryMock).findUserRoles(user);
}

§單元測試控制器

您可以使用 Play 的 測試輔助工具 來測試控制器,以擷取有用的屬性。

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static play.mvc.Http.Status.OK;
import static play.test.Helpers.*;

import javaguide.tests.controllers.HomeController;
import org.junit.Test;
import play.mvc.Result;
import play.twirl.api.Content;

public class ControllerTest {

  @Test
  public void testIndex() {
    Result result = new HomeController().index();
    assertEquals(OK, result.status());
    assertEquals("text/html", result.contentType().get());
    assertEquals("utf-8", result.charset().get());
    assertTrue(contentAsString(result).contains("Welcome"));
  }

}

§單元測試檢視範本

由於範本只是一個方法,您可以從測試中執行它並檢查結果

@Test
public void renderTemplate() {
    Content html = views.html.index.render("Welcome to Play!");
  assertEquals("text/html", html.contentType());
  assertTrue(contentAsString(html).contains("Welcome to Play!"));
}

§使用訊息進行單元測試

如果您需要 play.i18n.MessagesApi 執行個體進行單元測試,您可以使用 play.test.Helpers.stubMessagesApi() 來提供一個

@Test
public void renderMessages() {
  Langs langs = new Langs(new play.api.i18n.DefaultLangs());

  Map<String, String> messagesMap = Collections.singletonMap("foo", "bar");
  Map<String, Map<String, String>> langMap =
      Collections.singletonMap(Lang.defaultLang().code(), messagesMap);
  MessagesApi messagesApi = play.test.Helpers.stubMessagesApi(langMap, langs);

  Messages messages = messagesApi.preferred(langs.availables());
  assertEquals(messages.at("foo"), "bar");
}

下一步:撰寫功能測試


在此文件檔中發現錯誤?此頁面的原始程式碼可以在 這裡 找到。在閱讀 文件檔指南 後,請隨時提交拉取請求。有任何問題或建議要分享?請前往 我們的社群論壇 與社群展開對話。