Jmock学習ドキュメント


JMockはmockオブジェクトの作成を支援するツールで、Java開発に基づいてJavaテストと開発環境で比類のない優位性があり、さらに重要なのは、仮想オブジェクトの使用を大幅に簡素化することです.本論文では,JMockがこの孤立試験の実現にどのように役立つかを簡単な試験例によって説明する.私たちはあるクラスをテストするとき、他のクラスと連絡を取るため、このようなコードをテストする中でも連絡を取るクラスも一緒にテストすることが多い.このようなテストは、テストされたクラスを他のクラスに直接依存させ、他のクラスが変更されると、テストされたクラスも変更されます.さらに重要なのは、これらの他のクラスはまだテストされていない可能性があるため、テストされたクラスをテストするには、これらのクラスをテストする必要があります.この場合,テスト駆動開発は空論となる.他のクラスにも被テストクラスが引用されている場合、私たちはいったいどのクラスをテストしますか?したがって、テストでは、被テストクラスを孤立させ、他のクラスの具体的な実装に完全に依存しないようにすることができれば、どのクラスを先にテストし、それに関連するクラスが実装されているかどうかにかかわらず、どのクラスを先に実装することができます.
仮想オブジェクト(mock object)は、その必要性のために誕生したものです.JDKの反射メカニズムにより、実行時に動的に仮想オブジェクトを作成します.テストコードでは、これらの仮想オブジェクトが正しく呼び出されたかどうかを検証したり、明確な場合に特定の仮想値を返したりすることができます.これらの仮想オブジェクトが提供するサービスがあれば、被テストクラスは、仮想オブジェクトを他の実際のオブジェクトの身代わりとして使用することができ、簡単に完璧なテスト環境を構築することができます.
JMockはmockオブジェクトの作成を支援するツールで、Java開発に基づいてJavaテストと開発環境で比類のない優位性があり、さらに重要なのは、仮想オブジェクトの使用を大幅に簡素化することです.
本論文では,JMockがこの孤立試験の実現にどのように役立つかを簡単な試験例によって説明する.3つの主要なクラス、User、UserDAO、およびUserServiceがあります.この文書では、UserServiceをテストし、仮想UserDAOを準備するだけです.Userについては,自身が単純すぎるPOJOであるため,テストを行わなくてもよい.しかし、完璧主義者であれば、JMockの仮想を使用することもできます.この分野では、JMockはほとんどできません.:)
Userは、ビューでデータを転送したり、データベースをマッピングしたりするためのPOJOです.コードは次のとおりです.
package mock;
public class User {
private String name;
 
public User() {
}
 
public User(String name) {
this.name = name;
}
 
public String getName() {
return name;
}
 
public void setName(String name) {
this.name = name;
}
}

UserDAOはデータベースとの取引を担当し、データベースを通じてUserの情報を保存、取得する.JMockがJDKの反射機構によって孤立試験をどのように実現するかを知らなくてもよいが,少なくともJDKの反射機構はこれらの実行時に作成された動的クラスがインタフェースを定義しなければならないことを知っておくべきである.JMockを使用する環境では、仮想UserDAOを使用するため、UserDAOがインタフェースを定義する必要があることを意味します.コードは次のとおりです.
package mock;
public interface UserDAO {
public void saveUser(User user);
 
public User getUser(Long id);
}    

UserServiceには、アプリケーションレベルのサービスを外部に提供するUserDAOのリファレンスが格納されています.したがって、まずインタフェースを定義します(本明細書では、テストされたクラスとして、UserServiceにインタフェースは必要ありませんが、後でこのようなインタフェースが仮想化される必要がある場合は、インタフェースも定義する必要があります).
package mock;
 
public interface UserService {
public void setUserDAO(UserDAO userDAO);
 
public void saveUser(User user);
 
public User getUser(Long id);
}

setuUserDAO()に加えて,その他の方法はUserDAOと同様であることがわかる.これは設計モードにおけるゲートモードの典型的な応用であり、アプリケーションはUserServiceのみでサービスを提供し、UserServiceは内部でUserDAOを呼び出すことで対応する機能を実現する.
テスト先行の原則に基づいて、まずテストを書いてから、実現を書くべきです.ここでまず実現の原因を編纂して、主に読者に私たちが次に何をテストするかをもっとはっきりさせることです.ここではJMockの使用に重点を置いて説明し、UserServiceImplを加えると簡単なので、まずそのコードを以下のようにリストします.
package mock;
 
public class UserServiceImpl implements UserService {
private UserDAO userDAO;
 
public UserServiceImpl() {
}
 
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
 
public User getUser(Long id) {
return userDAO.getUser(id);
}
 
public void saveUser(User user) {
userDAO.saveUser(user);
}
}

次に、UserServiceのテストコードを示します.
package mock;
 
import junit.framework.Test;
import junit.framework.TestSuite;
 
import org.jmock.Mock;
import org.jmock.MockObjectTestCase;
 
public class UserServiceTest extends MockObjectTestCase {
private UserService userService = new UserServiceImpl();
private Mock userDAO = null;
 
public UserServiceTest(String testName) {
super(testName);
}
 
protected void setUp() throws Exception {
userDAO = new Mock(UserDAO.class);
userService.setUserDAO((UserDAO) userDAO.proxy());
}
 
protected void tearDown() throws Exception {
}
 
public static Test suite() {
TestSuite suite = new TestSuite(UserServiceTest.class);
return suite;
}
 
public void testGetUser() {
User fakeUser = new User("John");
userDAO.expects(once()).method("getUser").with(eq(1L)).will(returnValue(fakeUser));
User user = userService.getUser(1L);
assertNotNull(user);
assertEquals("John", user.getName());
}
 
public void testSaveUser() {
User fakeUser = new User("John");
userDAO.expects(once()).method("getUser").with(eq(1L)).will(returnValue(fakeUser));
User user = userService.getUser(1L);
assertEquals("John", user.getName());
userDAO.expects(once()).method("saveUser").with(same(fakeUser));
user.setName("Mike");
userService.saveUser(user);
userDAO.expects(once()).method("getUser").with(eq(1L)).will(returnValue(user));
User modifiedUser = userService.getUser(1L);
assertEquals("Mike", user.getName());
}
}

このコードには、次の点に注意してください.
1、このテストクラスはJMockのMockObjectTestCaseを継承している
    2、private Mock userDAO = null;説明userDaoは仮想オブジェクトの準備をしています
3、setup()でuserDAO.classがMock()に転送された後、proxy()メソッドでUserDAOのプロキシクラスインスタンス(仮想オブジェクトインスタンス)を返し、userServiceに値を割り当てます.
4、testGetUser()メソッドでは、最初の行と2行のコードをブロックすると、これは実際の環境でのテストコードであることがわかります.まずUserを取得し、空でない値を確認してから、名前が「John」であることを確認します.この場合、実際の環境では、このコードがテストに成功するには、UserDAOがデータベースに接続されていることを前提にして、Userを返してUserServiceに渡さなければなりません.しかし、問題は、これまで、UserDAOがデータベースへの接続という煩雑で苦痛なプロセスを経験していないことは言うまでもなく、UserDAOのインタフェースさえ実現していないことです.では、なぜ1行目と2行目のコードを付ければよいのでしょうか.これがJMockの威力だ.まず、テスト用のfakeUserをインスタンス化し、一連の命令を通じて、2行目のコードでJMockにどのように「偽」を作るべきかを教えます.このコードは長いが、1)userDAO.expects(once():userDAOのあるメソッドが1回実行されることを期待するが、このメソッドが実行されていないか、または2回以上実行されていない場合、テストは2)method(「getUser」)に合格しない:この1回実行されることを期待するメソッドの名前はuserDAOである.getUser()3)with(eq(1 L):getUser()メソッドを実行する場合、その入力パラメータ値が「1 L」4)will(returnValue(fakeUser):上記の条件が満たされた後、虚偽のオブジェクトを返す.すなわち、我々が前にインスタンス化したfakeUserは全体的に、2行目の文を設定すると、JMockはバックグラウンドで監視し、userDAOを確保する.getUser()は必須で、一度だけ実行され、パラメータ「1 L」はこのメソッドに正しく渡され、これらの条件が満たされるとfakeUserに戻ります.3行目では、User user=userServicesとなります.getUser(1 L)は、賞品fakeUserを受け入れ、userオブジェクトに付与する奨励として、これらの条件をすべてトリガーします.次の4行目と5行目は、このuserオブジェクトをテストします.合格しないのはおかしいです.
5)testSaveUser()メソッドの原理は類似している.IDが「1」のuserをデータベースから取り出し、名前を「Mike」に変更してデータベースに保存し、データベースからこのuserを取り出して名前が変更されたことを確認するという考え方です.5行目expects(once()).method("saveUser").with(same(fakeUser))は特殊です.まず、with(same(fakeUser))は、次の文でuser.setName(「Mike」)は名前のプロパティを変更しただけで、fakeUserのインスタンス参照は変更されていないため、条件を満たすことができます.次に、その後はありません.ウィル(returnValue)は、userDAOのためだ.saveUser()は、オブジェクトまたは基本データ型を返す必要はありません.また、userDAOを再度実行する.expects()の場合、JMockは監視条件をリセットします.私たちもuserDAOを通じてreset()は、モニタリング条件をクリアすることを明示的に示す.
以上のインスタンスコードとその説明から,JMockをうまく使う鍵は,まずモニタリング条件を設定し,対応するテスト文を書くことであることが分かった.モニタリング条件を設定した後、あるセグメントのコードブロックの実行が完了した場合、モニタリング条件が満たされていないか、expects()によって再び条件をリセットしていないか、reset()によってモニタリング条件を明示的にクリアしていない場合、テストは合格できません.
以上、JMockの基本的な使い方をご紹介しました.この基本的な使い方は、JMockを全面的に習得するために必要な知識の70%以上を占めています.JMockの詳細については、興味のある読者はJMockのサイトにアクセスしてさらに勉強することができます.
1