ユニットテストの方法について書きました。
その補足です。
@Afterアノテーションを付けた、テスト終了処理の実装についてですが、
LocalServiceTestHelper.tearDown()メソッドの呼び出しを
データストアを利用するメソッド呼び出しの前に行った場合には、
そのメソッド呼び出しが正しく行われません。
データストアに関連したオブジェクトも無効になります。
例を挙げると、エンティティを保存した時に取得したキーオブジェクトは
nullとなってしまいます。
インストール不要・無料の自製翻訳ツール、Kaede翻訳ツール(Translation Tool)の使い方・変更点などをつづるブログ。
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.appengine.tools.development.testing.LocalUserServiceTestConfig;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class AuthenticationTest {
private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalUserServiceTestConfig())
.setEnvIsAdmin(true).setEnvIsLoggedIn(true);
@Before
public void setUp() {
helper.setUp();
}
@After
public void tearDown() {
helper.tearDown();
}
@Test
public void testIsAdmin() {
UserService userService = UserServiceFactory.getUserService();
assertTrue(userService.isUserAdmin());
}
}
このサンプルでは、LocalServiceTestHelperをLocalUserServiceTestConfigを使って設定して、テスト上でUserServiceを利用できるようにしていますが、LocalServiceTestHelper上で、幾つかの認証に関する環境データの設定も行っています。
内のサンプルコードの訂正です。
メソッドdoTest()内の2行目と5行目内、withLimit(10) → FetchOptions.Builder.withLimit(10)
となります。この変更が行われないと、コンパイルエラーになってテストを実行できません。
この部分は、データストアからエンティティを取得する数の上限を設定するコードです。import com.google.appengine.api.taskqueue.dev.LocalTaskQueue;
import com.google.appengine.api.taskqueue.dev.QueueStateInfo;
import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.appengine.tools.development.testing.LocalTaskQueueTestConfig;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class TaskQueueTest {
private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalTaskQueueTestConfig());
@Before
public void setUp() {
helper.setUp();
}
@After
public void tearDown() {
helper.tearDown();
}
// Run this test twice to demonstrate we're not leaking state across tests.
// If we _are_ leaking state across tests we'll get an exception on the
// second test because there will already be a task with the given name.
private void doTest() throws InterruptedException {
QueueFactory.getDefaultQueue().add(TaskOptions.Builder.taskName("task29"));
// give the task time to execute if tasks are actually enabled (which they
// aren't, but that's part of the test)
Thread.sleep(1000);
LocalTaskQueue ltq = LocalTaskQueueTestConfig.getLocalTaskQueue();
QueueStateInfo qsi = ltq.getQueueStateInfo().get(QueueFactory.getDefaultQueue().getQueueName());
assertEquals(1, qsi.getTaskInfo().size());
assertEquals("task29", qsi.getTaskInfo().get(0).getTaskName());
}
@Test
public void testTaskGetsScheduled1() throws InterruptedException {
doTest();
}
@Test
public void testTaskGetsScheduled2() throws InterruptedException {
doTest();
}
}
注意する点として、LocalTaskqueueTestConfigにローカルサービスのインスタンスを操作させる方法と、ローカルサービスがタスクが予定されたとおりにスケジュールされていることを確実に行っていることを調べる、という点が挙げられます。全てのLocalServiceTestConfigの実装は、類似したメソッドを持っています。それらは常に必要とされるわけではありませんが、その存在が役に立つときがいつか来るでしょう。