ドメインに作成した
Blog
、
BlogEntry
、
BlogTable
、
BlogEntryTable
のテストケースを作成します。複雑な検証ロジックがある場合は検証クラス
BlogValidator
のテストケースも作成します。ここでは BlogTest と BlogTableTest を紹介し
ます。完全なソースは
BlogTest のソースコード
、
BlogEntryTest のソースコード
、
BlogTableTest のソースコード
、
BlogEntryTableTest のソースコード
を参照ください。
BlogTest では、post および store メソッドに対する
テストケースを紹介します。store メソッドでは、登録に成功、登録に失敗、更新に成功、更新に
失敗の4ケースをテストする必要があります。
public class BlogTest extends AbstractTransactionalTestsWithInitialData {
@Autowired BlogTable blogTable;
@Test
public void testStore登録() throws BlogCodeUsedByOtherException {
Blog blog = createBlog();
blog.store();
Blog actual = blogTable.find(blog.getId());
Assert.assertEquals(blog, actual);
}
@Test(expected=BlogCodeUsedByOtherException.class)
public void testStore登録を試みるがコードが重複()
throws BlogCodeUsedByOtherException {
Blog blog = createBlog();
blog.store();
Blog blog2 = blogTable.prototype(blog);
blog2.setId(null);
blog2.store();
}
@Test
public void testStore更新() throws BlogCodeUsedByOtherException {
Blog blog = createBlog();
blog.store();
blog.setCode("new_" + blog.getCode());
blog.getReadAccessControl().changeTo(AccessControlType.FRIEND_ONLY);
blog.store();
Blog actual = blogTable.find(blog.getId());
Assert.assertEquals(blog, actual);
}
@Test(expected=BlogCodeUsedByOtherException.class)
public void testStore更新を試みるがコードが重複()
throws BlogCodeUsedByOtherException {
Blog blog = createBlog();
blog.store();
Blog blog2 = blogTable.prototype(blog);
blog2.setId(null);
blog2.setCode(blog2.getCode() + "2");
blog2.store();
blog2.setCode(blog.getCode());
blog2.store();
}
@Test
public void testPost() throws BlogCodeUsedByOtherException {
Blog blog = createBlog();
blog.store();
BlogEntry blogEntry = createBlogEntry(blog.getReadAccessControl(),
blog.getWriteAccessControl());
blog.retrieveBlogEntries(0, 1);
Assert.assertSame(0, blog.getBlogEntries().size());
blog.post(blogEntry);
blog.retrieveBlogEntries(0, 1);
Assert.assertSame(1, blog.getBlogEntries().size());
Assert.assertEquals(blogEntry, blog.getBlogEntries().get(0));
}
// other test methods
private Blog createBlog() {
// テスト用のブログを生成
}
private BlogEntry createBlogEntry(AccessControl readAccessControl,
AccessControl writeAccessControl) {
// テスト用のブログ記事を生成
}
}
BlogTable
は SimpleTableModule
を継承したクラスであるため、それに対応する BlogTableTest は TableModuleTestCaseSupport
を継承することで基本的なテストケースを再利用できます。BlogTable
は独自メソッド findByCode を持っていますが、このメソッドは単にデータアクセスオブジェクトに
処理を委譲しているだけですので、テストケースは作成していません。
public class BlogTableTest extends TableModuleTestCaseSupport<Blog> {
@Autowired private BlogTable blogTable;
@Override
protected Blog createDomain() {
// テスト用のブログを生成
}
@Override
protected SimpleDomainsSupport<Blog> getTableModule() {
return blogTable;
}
@Override
protected SimpleFindable<Blog> getSimpleDao() {
return blogTable.getSimpleDao();
}
}
ドメイン設計時に実装を保留した箇所を実装します。全てのテストに合格すれば、実装完了です。ドメインの完全なソー
スコードは Blog のソースコード
、
BlogEntry のソースコード
、
BlogTable のソースコード
、
BlogEntryTable のソースコード
を参照ください。
Blog
の store メソッドでは、コードが重複しないことを確認してから永続化処理を行っています。また、
delete メソッドでは、関連するブログ記事が存在しないことを確認してから削除処理を行っていま
す。
public class Blog ... {
// ...
@Override
public void store() throws BlogCodeUsedByOtherException {
Blog foundByCode = blogDao.findByCode(code);
if (foundByCode != null && !foundByCode.identify(this)) {
String message = "The code '" + code
+ "' has already been used by other.";
logger.warn(message);
throw new BlogCodeUsedByOtherException(message);
}
if (this.id == null) {
blogDao.register(this);
} else {
blogDao.update(this);
}
}
@Override
public void delete() throws BlogEntryExistException {
int count = blogDao.countBlogEntry(id);
if (count > 0) {
String message = "The blog [ID=" + id + "] has " + count
+ " entries.";
logger.warn(message);
throw new BlogEntryExistException(message);
}
blogDao.delete(id);
}
public void post(BlogEntry blogEntry) {
blogEntry.store();
blogDao.registerBlogEntry(id, blogEntry.getId());
}
public void retrieveEntries(int no, int num) {
entries = blogDao.findBlogEntries(id, no, num);
}
// ...
}
BlogEntry
の delete メソッドでは、関連する全てのコメントを削除しています。
public class BlogEntry ... {
// ...
@Override
public void store() {
try {
entry.store();
} catch (MessageCodeUsedByOtherException e) {
// 起こらない。記事のコードは自動生成される。
logger.error(e);
throw new IllegalStateException(e);
}
}
@Override
public void delete() {
entry.delete();
}
public void retrieveComments() {
comments = blogDao.findComments(getId());
}
public void post(Comment comment) {
comment.store();
blogDao.registerComment(getId(), comment.getId());
}
// ...
}
最後に applicationContext-dao.xml
および applicationContext-domain.xml
に作成したデータアクセスオブジェクトおよびドメインクラスを記載して完了です。未定義の BlogValidator
は applicationContext-domain.xml
に追記します。
<bean id="communication.blogValidator"
class="org.unitedfront2.domain.communication.BlogValidator">
<property name="blogTable" ref="communication.blogTable"/>
</bean>