Sunday, May 22, 2005

jMock

ใน Application ที่ AppFuse generate มาให้นั้น
มีตัวอย่างการ test service layer โดยใช้ Mock Object ด้วย
โดยตัว Tool ที่ทาง AppFuse เลือกใช้ ก็คือ jMock

หลักการก็คือ สมมติว่าเรามี Service ที่ชื่อ AuthenticateService อยู่
class AuthenticateService {
private UserDao userDao;

public boolean isAuthenticate(String userId, String passwd) {
User user = userDao.getUser(userId);
if (user != null && user.getPassword().equals(passwd)) {
return true;
}
return false;
}

public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}


ตัว AuthenticateService เรียกใช้ UserDao
โดย UserDao จะค้นหา user จาก persistent layer ให้
interface UserDao {
public User getUser(String userId);
}


ในการ test กรณีที่เราต้องการ test unit เฉพาะ
AuthenticateService ว่า logic ทำงานถูกต้องหรือไม่
โดยไม่ต้องการลากเอา Persistent Layer หรือ Dao มา test ด้วย
ก็ทำได้โดยใช้ Mock Object เข้ามาช่วย

เริ่มโดยการเขียน TestCase ที่ extends MockObjectTestCase
public class AuthenticateServiceTest extends MockObjectTestCase {
public void testAuthenticate() {

}
}


จากนั้นใน test method เราก็จะทำการ setup Mock Object ก่อน

Mock userDaoMock = new Mock(UserDao.class);
AuthenticateService svr = new AuthenticateService();
svr.setuserDao(userDaoMock.proxy());


ก่อน test เราก็ setup ค่าที่เราคาดหวังไว้ให้
mock ตอบกลับออกมาเมื่อมีการเรียกใช้
method getUser

User userData = new User();
userData.setUserId("tomcat");
userData.setPassword("testIt");

userDaoMock.expects(once()).method("getuser")
.with(eq("tomcat")).will(returnValue(userData));


จากนั้นก็เป็นเริ่ม test
โดย assert ผลลัพท์ที่ได้จากการ call isAuthenticate

boolean result = svr.isAuthenticate("tomcat", "testIt");
assertTrue(result);
result = svr.isAuthenticate("tomcat", "blabla");
assertFalse(result);
userDaoMock.verify();


หลายคนที่เคย test ระบบที่มี dependency
อีรุงตุนังไปหมดนั้นคงรู้ว่ามันยากต่อการ run test ขนาดไหน
แต่จะเห็นได้ว่าการใช้ mock เข้ามาช่วยนั้น
จะทำให้เราสามารถ Isolate การ test ออกเป็นส่วนย่อยๆได้
ซึ่งทำให้ง่ายต่อการ test และ test ซ้ำได้ง่ายขึ้น

Related link from Roti

No comments: