§測試您的應用程式
為您的應用程式撰寫測試可能是一個複雜的過程。Play 支援 JUnit,並提供輔助程式和應用程式程式碼片段,讓測試您的應用程式變得盡可能容易。
§概觀
測試的位置在「test」資料夾中。在測試資料夾中建立了兩個範例測試檔案,可用作範本。
您可以在 sbt 主控台中執行測試。
- 若要執行所有測試,請執行
test
。 - 若要只執行一個測試類別,請執行
testOnly
,後接類別名稱,例如testOnly my.namespace.MyTest
。 - 若要只執行失敗的測試,請執行
testQuick
。 - 若要持續執行測試,請執行前面加上波浪符號的指令,例如
~testQuick
。 - 若要在主控台中存取測試輔助程式,例如
FakeApplication
,請執行Test/console
。
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());
}
}
注意:每次執行
test
或test-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");
}
下一步:撰寫功能測試
在此文件檔中發現錯誤?此頁面的原始程式碼可以在 這裡 找到。在閱讀 文件檔指南 後,請隨時提交拉取請求。有任何問題或建議要分享?請前往 我們的社群論壇 與社群展開對話。