Pengujian Unit Lokal untuk Java 8

Pengujian unit memungkinkan Anda memeriksa kualitas kode setelah menulisnya, tetapi Anda juga dapat menggunakan pengujian unit untuk meningkatkan proses pengembangan seiring progres Anda. Daripada menulis pengujian setelah Anda selesai mengembangkan aplikasi, sebaiknya tulis pengujian seiring progres Anda. Hal ini membantu Anda mendesain unit kode yang kecil, mudah dikelola, dan dapat digunakan kembali. Hal ini juga memudahkan Anda menguji kode secara menyeluruh dan cepat.

Saat melakukan pengujian unit lokal, Anda menjalankan pengujian yang tetap berada di dalam lingkungan pengembangan Anda sendiri tanpa melibatkan komponen jarak jauh. App Engine menyediakan utilitas pengujian yang menggunakan implementasi lokal datastore dan layanan App Engine lainnya. Ini berarti Anda dapat menerapkan penggunaan kode Anda atas layanan ini secara lokal, tanpa men-deploy kode ke App Engine, dengan menggunakan service stub.

Service stub adalah metode yang menyimulasikan perilaku layanan. Misalnya, service stub datastore yang ditampilkan dalam Menulis Pengujian Datastore dan Memcache memungkinkan Anda menguji kode datastore tanpa membuat permintaan ke datastore sebenarnya. Setiap entity yang disimpan selama pengujian unit datastore akan disimpan di memori, bukan di datastore, dan dihapus setelah pengujian dijalankan. Anda dapat menjalankan pengujian kecil dan cepat tanpa dependensi pada datastore itu sendiri.

Dokumen ini memberikan beberapa informasi tentang penyiapan framework pengujian, lalu menjelaskan cara menulis pengujian unit terhadap beberapa layanan App Engine lokal.

Menyiapkan framework pengujian

Meskipun utilitas pengujian SDK tidak terikat dengan framework tertentu, panduan ini menggunakan JUnit untuk contoh sehingga Anda memiliki sesuatu yang konkret dan lengkap untuk dikerjakan. Sebelum mulai menulis pengujian, Anda harus menambahkan JUnit 4 JAR yang sesuai ke classpath pengujian. Setelah selesai, Anda siap untuk menulis pengujian JUnit yang sangat sederhana.


import static org.junit.Assert.assertEquals;

import org.junit.Test;

public class MyFirstTest {
  @Test
  public void testAddition() {
    assertEquals(4, 2 + 2);
  }
}

Jika Anda menjalankan Eclipse, pilih file sumber pengujian yang akan dijalankan. Pilih Jalankan > Jalankan Sebagai > Pengujian JUnit. Hasil pengujian akan muncul di jendela Konsol.

Memperkenalkan utilitas pengujian Java 8

MyFirstTest menunjukkan penyiapan pengujian yang paling sederhana, dan untuk pengujian yang tidak memiliki dependensi pada App Engine API atau implementasi layanan lokal, Anda mungkin tidak memerlukan hal lain. Namun, jika pengujian atau kode yang sedang diuji memiliki dependensi ini, tambahkan file JAR berikut ke classpath pengujian Anda:

  • ${SDK_ROOT}/lib/impl/appengine-api.jar
  • ${SDK_ROOT}/lib/impl/appengine-api-stubs.jar
  • ${SDK_ROOT}/lib/appengine-tools-api.jar

JAR ini membuat API runtime dan implementasi lokal API tersebut tersedia untuk pengujian Anda.

Layanan App Engine memperkirakan sejumlah hal dari lingkungan eksekusinya, dan penyiapan hal-hal ini melibatkan cukup banyak kode boilerplate. Daripada menyiapkannya sendiri, Anda dapat menggunakan utilitas dalam paket com.google.appengine.tools.development.testing. Untuk menggunakan paket ini, tambahkan file JAR berikut ke classpath pengujian Anda:

  • ${SDK_ROOT}/lib/testing/appengine-testing.jar

Luangkan waktu untuk menjelajahi javadoc untuk paket com.google.appengine.tools.development.testing. Class terpenting dalam paket ini adalah LocalServiceTestHelper, yang menangani semua penyiapan lingkungan yang diperlukan dan memberi Anda titik konfigurasi level teratas untuk semua layanan lokal yang mungkin ingin Anda akses dalam pengujian.

Untuk menulis pengujian yang mengakses layanan lokal tertentu:

  • Buat instance LocalServiceTestHelper dengan implementasi LocalServiceTestConfig untuk layanan lokal spesifik tersebut.
  • Panggil setUp() pada instance LocalServiceTestHelper Anda sebelum setiap pengujian dan tearDown() setelah setiap pengujian.

Menulis pengujian Datastore dan memcache

Contoh berikut menguji penggunaan layanan datastore.


import static com.google.appengine.api.datastore.FetchOptions.Builder.withLimit;
import static org.junit.Assert.assertEquals;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class LocalDatastoreTest {

  private final LocalServiceTestHelper helper =
      new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());

  @Before
  public void setUp() {
    helper.setUp();
  }

  @After
  public void tearDown() {
    helper.tearDown();
  }

  // Run this test twice to prove we're not leaking any state across tests.
  private void doTest() {
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
    assertEquals(0, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
    ds.put(new Entity("yam"));
    ds.put(new Entity("yam"));
    assertEquals(2, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
  }

  @Test
  public void testInsert1() {
    doTest();
  }

  @Test
  public void testInsert2() {
    doTest();
  }
}

Dalam contoh ini, LocalServiceTestHelper menyiapkan dan merombak bagian-bagian lingkungan eksekusi yang umum untuk semua layanan lokal, dan LocalDatastoreServiceTestConfig menyiapkan dan merombak bagian-bagian lingkungan eksekusi yang spesifik untuk layanan datastore lokal. Jika membaca javadoc, Anda akan mengetahui bahwa hal ini melibatkan konfigurasi layanan datastore lokal untuk mempertahankan semua data dalam memori (bukan melakukan pengosongan ke disk secara berkala) dan menghapus semua data dalam memori di akhir setiap pengujian. Ini hanyalah perilaku default untuk pengujian datastore dan jika perilaku ini tidak diinginkan, Anda dapat mengubahnya.

Mengubah contoh untuk mengakses memcache, bukan datastore

Untuk membuat pengujian yang mengakses layanan memcache lokal, Anda dapat menggunakan kode yang ditunjukkan di atas, dengan beberapa perubahan kecil.

Daripada mengimpor class yang terkait dengan datastore, impor class yang terkait dengan memcache. Anda masih perlu mengimpor LocalServiceTestHelper.

Ubah nama class yang Anda buat dan ubah instance LocalServiceTestHelper, sehingga bersifat spesifik untuk memcache.

public class LocalMemcacheTest {

  private final LocalServiceTestHelper helper =
      new LocalServiceTestHelper(new LocalMemcacheServiceTestConfig());

Dan terakhir, ubah cara Anda dalam menjalankan pengujian sehingga relevan dengan memcache.

private void doTest() {
  MemcacheService ms = MemcacheServiceFactory.getMemcacheService();
  assertFalse(ms.contains("yar"));
  ms.put("yar", "foo");
  assertTrue(ms.contains("yar"));
}

Seperti dalam contoh datastore, LocalServiceTestHelper dan LocalServiceTestConfig khusus layanan (dalam hal ini LocalMemcacheServiceTestConfig) akan mengelola lingkungan eksekusi.

Menulis pengujian Cloud Datastore

Jika aplikasi Anda menggunakan Cloud Datastore, Anda mungkin ingin menulis pengujian yang memverifikasi perilaku aplikasi dalam menghadapi konsistensi tertunda. LocalDatastoreServiceTestConfig mengekspos opsi yang memudahkan ini:


import static com.google.appengine.api.datastore.FetchOptions.Builder.withLimit;
import static org.junit.Assert.assertEquals;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class LocalHighRepDatastoreTest {

  // Maximum eventual consistency.
  private final LocalServiceTestHelper helper =
      new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
          .setDefaultHighRepJobPolicyUnappliedJobPercentage(100));

  @Before
  public void setUp() {
    helper.setUp();
  }

  @After
  public void tearDown() {
    helper.tearDown();
  }

  @Test
  public void testEventuallyConsistentGlobalQueryResult() {
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
    Key ancestor = KeyFactory.createKey("foo", 3);
    ds.put(new Entity("yam", ancestor));
    ds.put(new Entity("yam", ancestor));
    // Global query doesn't see the data.
    assertEquals(0, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
    // Ancestor query does see the data.
    assertEquals(2, ds.prepare(new Query("yam", ancestor)).countEntities(withLimit(10)));
  }
}

Dengan menetapkan persentase tugas yang belum diterapkan ke 100, kita menginstruksikan datastore lokal untuk beroperasi dengan jumlah konsistensi tertunda maksimum. Konsistensi tertunda maksimum berarti penulisan akan di-commit, tetapi selalu gagal diterapkan, sehingga kueri global (non-ancestor) akan terus gagal melihat perubahan. Ini tentu saja tidak mewakili jumlah konsistensi tertunda yang akan dilihat aplikasi Anda saat berjalan dalam produksi. Namun, untuk tujuan pengujian, sangat berguna untuk dapat mengonfigurasi datastore lokal agar berperilaku seperti ini setiap saat.

Jika ingin kontrol lebih detail atas transaksi mana yang gagal diterapkan, Anda dapat mendaftarkan HighRepJobPolicy Anda sendiri:


import static com.google.appengine.api.datastore.FetchOptions.Builder.withLimit;
import static org.junit.Assert.assertEquals;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.dev.HighRepJobPolicy;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class LocalCustomPolicyHighRepDatastoreTest {
  private static final class CustomHighRepJobPolicy implements HighRepJobPolicy {
    static int newJobCounter = 0;
    static int existingJobCounter = 0;

    @Override
    public boolean shouldApplyNewJob(Key entityGroup) {
      // Every other new job fails to apply.
      return newJobCounter++ % 2 == 0;
    }

    @Override
    public boolean shouldRollForwardExistingJob(Key entityGroup) {
      // Every other existing job fails to apply.
      return existingJobCounter++ % 2 == 0;
    }
  }

  private final LocalServiceTestHelper helper =
      new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
          .setAlternateHighRepJobPolicyClass(CustomHighRepJobPolicy.class));

  @Before
  public void setUp() {
    helper.setUp();
  }

  @After
  public void tearDown() {
    helper.tearDown();
  }

  @Test
  public void testEventuallyConsistentGlobalQueryResult() {
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
    ds.put(new Entity("yam")); // applies
    ds.put(new Entity("yam")); // does not apply
    // First global query only sees the first Entity.
    assertEquals(1, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
    // Second global query sees both Entities because we "groom" (attempt to
    // apply unapplied jobs) after every query.
    assertEquals(2, ds.prepare(new Query("yam")).countEntities(withLimit(10)));
  }
}

API pengujian berguna untuk memverifikasi bahwa aplikasi Anda berperilaku dengan baik dalam menghadapi konsistensi tertunda, tetapi perlu diingat bahwa model konsistensi pembacaan Replikasi Tinggi lokal adalah perkiraan dari model konsistensi pembacaan Replikasi Tinggi produksi, bukan replika yang sama persis. Di lingkungan lokal, menjalankan get() dari Entity yang termasuk dalam grup entity dengan penulisan yang belum diterapkan akan selalu membuat hasil penulisan yang belum diterapkan terlihat oleh kueri global berikutnya. Dalam produksi, hal ini tidak terjadi.

Menulis pengujian task queue

Pengujian yang menggunakan task queue lokal akan sedikit lebih rumit karena, tidak seperti datastore dan memcache, API task queue tidak mengekspos fasilitas untuk memeriksa status layanan. Kita perlu mengakses task queue lokal itu sendiri untuk memverifikasi bahwa tugas telah dijadwalkan dengan parameter yang diharapkan. Untuk melakukannya, kita memerlukan com.google.appengine.api.taskqueue.dev.LocalTaskQueue.


import static org.junit.Assert.assertEquals;

import com.google.appengine.api.taskqueue.QueueFactory;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.appengine.api.taskqueue.dev.LocalTaskQueue;
import com.google.appengine.api.taskqueue.dev.QueueStateInfo;
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;

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.withTaskName("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();
  }
}

Perhatikan cara kita meminta LocalTaskqueueTestConfig untuk handle ke instance layanan lokal, lalu kita menyelidiki layanan lokal itu sendiri untuk memastikan tugas tersebut dijadwalkan seperti yang diharapkan. Semua implementasi LocalServiceTestConfig mengekspos metode yang serupa. Anda mungkin tidak selalu membutuhkannya, tapi cepat atau lambat Anda akan senang sistem itu ada di sana.

Menyetel file konfigurasi queue.xml

Library pengujian task queue memungkinkan berapa pun konfigurasi queue.xml untuk ditentukan berdasarkan per-LocalServiceTestHelper melalui metode LocalTaskQueueTestConfig.setQueueXmlPath. Saat ini, setelan pembatasan kapasitas antrean diabaikan oleh server pengembangan lokal. Anda tidak dapat menjalankan beberapa tugas serentak pada satu waktu secara lokal.

Misalnya, project mungkin perlu diuji terhadap file queue.xml yang akan diupload dan digunakan oleh aplikasi App Engine. Dengan asumsi bahwa file queue.xml berada di lokasi standar, kode contoh di atas dapat dimodifikasi sebagai berikut untuk memberikan akses pengujian ke antrean yang ditentukan dalam file src/main/webapp/WEB-INF/queue.xml:

private final LocalServiceTestHelper helper =
    new LocalServiceTestHelper(new LocalTaskQueueTestConfig()
        .setQueueXmlPath("src/main/webapp/WEB-INF/queue.xml"));

Ubah jalur ke file queue.xml agar sesuai dengan struktur file project Anda.

Gunakan metode QueueFactory.getQueue untuk mengakses antrean berdasarkan nama:

QueueFactory.getQueue("my-queue-name").add(TaskOptions.Builder.withTaskName("task29"));

Menulis pengujian tugas yang ditangguhkan

Jika kode aplikasi Anda menggunakan Tugas yang Ditangguhkan, Java Testing Utilities akan memudahkan penulisan pengujian integrasi yang memverifikasi hasil tugas tersebut.


import static org.junit.Assert.assertTrue;

import com.google.appengine.api.taskqueue.DeferredTask;
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 java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class DeferredTaskTest {

  // Unlike CountDownLatch, TaskCountDownlatch lets us reset.
  private final LocalTaskQueueTestConfig.TaskCountDownLatch latch =
      new LocalTaskQueueTestConfig.TaskCountDownLatch(1);

  private final LocalServiceTestHelper helper =
      new LocalServiceTestHelper(new LocalTaskQueueTestConfig()
          .setDisableAutoTaskExecution(false)
          .setCallbackClass(LocalTaskQueueTestConfig.DeferredTaskCallback.class)
          .setTaskExecutionLatch(latch));

  private static class MyTask implements DeferredTask {
    private static boolean taskRan = false;

    @Override
    public void run() {
      taskRan = true;
    }
  }

  @Before
  public void setUp() {
    helper.setUp();
  }

  @After
  public void tearDown() {
    MyTask.taskRan = false;
    latch.reset();
    helper.tearDown();
  }

  @Test
  public void testTaskGetsRun() throws InterruptedException {
    QueueFactory.getDefaultQueue().add(
        TaskOptions.Builder.withPayload(new MyTask()));
    assertTrue(latch.await(5, TimeUnit.SECONDS));
    assertTrue(MyTask.taskRan);
  }
}

Seperti contoh Task Queue Lokal pertama, kita menggunakan LocalTaskqueueTestConfig, namun kali ini kita menginisialisasinya dengan beberapa argumen tambahan yang memberi kita cara mudah untuk memverifikasi bahwa tidak hanya tugas tersebut dijadwalkan tetapi juga tugas telah dieksekusi: Kita memanggil setDisableAutoTaskExecution(false) untuk memberi tahu Task Queue Lokal untuk mengeksekusi tugas secara otomatis. Kita memanggil setCallbackClass(LocalTaskQueueTestConfig.DeferredTaskCallback.class) untuk memberi tahu Tas Queue Lokal agar menggunakan callback yang memahami cara mengeksekusi Tugas yang ditangguhkan. Dan terakhir kita memanggil setTaskExecutionLatch(latch) untuk memberi tahu Task Queue Lokal agar mengurangi latch setelah setiap eksekusi tugas. Konfigurasi ini memungkinkan kita menulis pengujian tempat kita mengantrekan Tugas yang ditangguhkan, menunggu hingga tugas tersebut berjalan, lalu memverifikasi bahwa tugas tersebut berperilaku seperti yang diharapkan saat dijalankan.

Menulis pengujian kemampuan layanan lokal

Pengujian kemampuan melibatkan perubahan status beberapa layanan, seperti datastore, blobstore, memcache, dan sebagainya, serta menjalankan aplikasi terhadap layanan tersebut untuk menentukan apakah aplikasi Anda merespons seperti yang diharapkan dalam kondisi yang berbeda. Status kemampuan dapat diubah menggunakan class LocalCapabilitiesServiceTestConfig.

Cuplikan kode berikut mengubah status kemampuan layanan datastore menjadi nonaktif, lalu menjalankan pengujian pada layanan datastore. Anda dapat mengganti layanan lain untuk datastore sesuai kebutuhan.


import static org.junit.Assert.assertEquals;

import com.google.appengine.api.capabilities.Capability;
import com.google.appengine.api.capabilities.CapabilityStatus;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.tools.development.testing.LocalCapabilitiesServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.apphosting.api.ApiProxy;
import org.junit.After;
import org.junit.Test;

public class ShortTest {
  private LocalServiceTestHelper helper;

  @After
  public void tearDown() {
    helper.tearDown();
  }

  @Test(expected = ApiProxy.CapabilityDisabledException.class)
  public void testDisabledDatastore() {
    Capability testOne = new Capability("datastore_v3");
    CapabilityStatus testStatus = CapabilityStatus.DISABLED;
    // Initialize the test configuration.
    LocalCapabilitiesServiceTestConfig config =
        new LocalCapabilitiesServiceTestConfig().setCapabilityStatus(testOne, testStatus);
    helper = new LocalServiceTestHelper(config);
    helper.setUp();
    FetchOptions fo = FetchOptions.Builder.withLimit(10);
    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
    assertEquals(0, ds.prepare(new Query("yam")).countEntities(fo));
  }
}

Pengujian contoh akan terlebih dahulu membuat objek Capability yang diinisialisasi ke datastore, lalu membuat objek CapabilityStatus yang disetel ke DINONAKTIFKAN. LocalCapabilitiesServiceTestConfig dibuat dengan kemampuan dan status yang disetel menggunakan objek Capability dan CapabilityStatus yang baru saja dibuat.

LocalServiceHelper kemudian dibuat menggunakan objek LocalCapabilitiesServiceTestConfig. Sekarang setelah pengujian disiapkan, DatastoreService dibuat dan Kueri dikirim ke sana untuk menentukan apakah pengujian memberikan hasil yang diharapkan. Dalam hal ini, CapabilityDisabledException.

Menulis pengujian untuk layanan lain

Utilitas pengujian tersedia untuk blobstore dan layanan App Engine lainnya. Untuk mengetahui daftar semua layanan yang memiliki implementasi lokal untuk pengujian, lihat dokumentasi LocalServiceTestConfig.

Menulis pengujian dengan ekspektasi autentikasi

Contoh ini menunjukkan cara menulis pengujian yang memverifikasi logika yang menggunakan UserService untuk menentukan apakah pengguna sudah login atau memiliki hak istimewa admin. Perhatikan bahwa setiap pengguna dengan peran dasar Viewer, Editor, atau Pemilik, atau peran Admin Aplikasi App Engine yang telah ditetapkan sebelumnya memiliki hak istimewa admin.


import static org.junit.Assert.assertTrue;

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;

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());
  }
}

Dalam contoh ini, kita mengonfigurasi LocalServiceTestHelper dengan LocalUserServiceTestConfig sehingga kita dapat menggunakan UserService dalam pengujian, tetapi juga mengonfigurasi beberapa data lingkungan terkait autentikasi pada LocalServiceTestHelper itu sendiri.

Dalam contoh ini, kita mengonfigurasi LocalServiceTestHelper dengan LocalUserServiceTestConfig sehingga kita dapat menggunakan OAuthService.