Play Framework - Testing
Để tiếp tục về những bài viết về Play framework khác. Hôm nay mình muốn viết về việc viết test cho ứng dụng của mình. Play hỗ trợ JUnit, là một bộ thư viện có sẵn hỗ trợ viết unit test và chạy test của mình. Đây là 1 ví dụ nhỏ import static org . junit . Assert . * ; import org . ...
Để tiếp tục về những bài viết về Play framework khác. Hôm nay mình muốn viết về việc viết test cho ứng dụng của mình.
Play hỗ trợ JUnit, là một bộ thư viện có sẵn hỗ trợ viết unit test và chạy test của mình. Đây là 1 ví dụ nhỏ
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()); } }
Assertions & Matchers
Một số developpers thích viết test theo một cách chuyên nghiệp hơn JUnit. Những thư viện phổ biến cho việc so sánh với những thuận tiện hơn.
Ví dụ về sử dụng Hamcrest matchers.
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"))); } }
Mocks.
Mocks được sử dụng để độc lập việc viết test với các dependencies bên ngoài. Ví dụ, nếu bạn muốn viết test phụ thuộc vào dữ liệu từ class bên ngoài. Bạn có thể làm giả nó để cung cấp data cho việc viết test.
Thư viện Mockito được cung cấp trong project để cho chúng ta sử dụng.
Với Mockito, bạn có thể giả những class và interface như sau:
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); Unit testing models Giả sử chúng ta có model như sau 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; } }
Một cách tiếp cận phổ biến cho việc test này là giữ model độc lập với database và với logic nhiều nhất có thể. Thay vào đó, truy cập với một repository interface.
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 ... } }
Sau đó sử dụng một service có interface đó để tương tác với models:
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; } }
Bằng cách này. Method isAdmin có thể được test bằng việc làm giả UserRepository dependency
@@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); }
Controller Testing Cuối cùng mình muốn giới thiệu cách để viết test trong controllers của Play app. Play cung cấp một tập các Helper để phục vụ việc này. Ví dụ
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 java.util.ArrayList; import com.google.common.collect.ImmutableMap; import org.junit.Test; import play.Application; import play.inject.guice.GuiceApplicationBuilder; import play.mvc.Result; import play.test.Helpers; import play.test.WithApplication; import play.twirl.api.Content; public class ApplicationTest extends WithApplication { @@Override protected Application provideApplication() { return new GuiceApplicationBuilder() .configure("play.http.router", "javaguide.tests.Routes") .build(); } @@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")); } }
Bạn có thể refer đến router và gọi chúng. Điều này cho phép bạn sử dụng FakeRequest (Mock request)
@Test public void testCallIndex() { Result result = route( fakeRequest() ); assertEquals(OK, result.status()); }
Unit testing view templates
Bạn cũng có thể viết test cho các template của Play app Ví dụ
@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 còn cung cấp nhiều cách để viết functional test cho Play App. Mình xin phép đề cập trong bài viết sau. Hẹn gặp lại mọi người. Thanks