Bagaimana saya bisa menguji layanan web REST saya?

16

Saya baru mengenal unit testing, saya punya satu metode web REST yang hanya memanggil DB dan mengisi DTO. Kode semu adalah

public object GetCustomer(int id)
{
  CustomerDTO objCust = //get from DB
  return objCust;
}

Keraguan saya adalah bagaimana menulis tes untuk metode dan jenis tes ini (Integrasi / Unit) untuk dimasukkan. Dan untuk unit test, apakah perlu menekan DB. Jika itu dan saya melewati id pelanggan dan melakukan beberapa pernyataan, data mungkin berubah pada akhirnya mengakibatkan kegagalan.

Saya pikir saya kehilangan sesuatu di sini untuk memahami konsep-konsep ini.

Cerah
sumber
5
Dalam kode yang Anda kirim, hal-hal yang harus diuji adalah: (1) Dapatkah Anda memanggil GetCustomer dengan int sebagai parameter. (2) Apakah itu mengembalikan objek CustomerDTO? (3) Apakah objek tersebut terisi dari DB seperti yang diharapkan. (4) Apakah perilaku yang diharapkan terjadi jika dipanggil dengan int yang tidak sesuai dengan pelanggan yang valid? Belum ada yang ada hubungannya dengan REST. Ketika Anda siap untuk menulis kode yang menanggapi permintaan RESTful, maka Anda akan menulis tes untuk itu.
DavidO
@ Davidvid: "Apakah objek itu diisi dari DB seperti yang diharapkan." Jelas bukan unit test (dalam hal kode OP). Itu tes integrasi.
Flater
Ya kamu benar. Jika saya bisa kembali dan mengubah komentar untuk menyebutkan bahwa dalam tes integrasi Anda akan memverifikasi komponen DB, dan jika tidak mengejeknya, saya akan melakukan edit itu, tetapi jendela edit untuk komentar jika 5 menit, dan komentar dibuat enam bertahun-tahun lalu. :)
DavidO

Jawaban:

18

Saat pengujian unit Anda tidak diharapkan untuk menguji dengan database, atau setidaknya, tidak dengan database yang belum Anda siapkan untuk pengujian unit. Menguji dengan database, dan dengan demikian, menguji berbagai lapisan aplikasi Anda pada saat yang sama umumnya dilihat sebagai tes integrasi . Dengan unit test Anda seharusnya hanya menguji apa metode Anda, apa yang dikembalikan tergantung pada parameter yang berbeda, dan kapan (atau tidak) itu harus gagal.

Sangat diharapkan bahwa dalam metode Anda, Anda membuat panggilan ke metode X dari kelas lain. Anda tidak menguji metode X ini sehingga yang harus Anda lakukan adalah mengejek metode ini.

Saya kira Anda sedang menulis kode di Jawa, dalam hal ini Anda memiliki kerangka kerja mengejek yang hebat seperti Mockito yang mungkin membantu Anda. Apakah Anda menggunakan kerangka mengejek atau tidak adalah pilihan Anda, saya hanya akan mengatakan mereka akan menghemat banyak waktu dan yang saya sebutkan setidaknya benar-benar tidak rumit.

Jika Anda hanya ingin menulis tiruan sendiri untuk bereksperimen, anggaplah Anda memiliki CustomerRepositorykelas berikut :

public class CustomerRepository {
 public CustomerDTO getCustomer(int id) {
   ...
 }
}

Anda dapat menulis sendiri mengejek dan kotor Anda CustomerRepositorykelas dengan cara berikut:

public class MockedCustomerRepository extends CustomerRepository {
 public boolean bThrowDatabaseException;
 public boolean bReturnNull;
 public boolean bReturnCustomerWrongId;
 public boolean bReturnCustomerWithId;
 public CustomerDTO getCustomer(int id) {
  if(bThrowDatabaseException) { 
    throw new DatabaseException("xxx"); 
  } else if(bReturnNull) { 
    return null; 
  } else if(bReturnCustomerWrongId) { 
    throw new CustomerNotExistException(id);
  } else if(bReturnCustomerWithId) { 
    return new CustomerDTO(id); 
  }
 }
}

Kemudian, dalam kasus pengujian Anda, pada dasarnya Anda mengganti instance "standar" Anda CustomerRepositorydengan instance tiruan yang akan memungkinkan Anda menguji metode Anda untuk berbagai hasil dari getCustomer:

public class CustomerRestTest {
  public void testGetCustomer_databaseFailure() {
    MockedCustomerRepository dto = new MockedCustomerRepository();
    dto.bThrowDataBaseException = true;
    yRestClass rest = new MyRestClass();
    rest.dto = dto;
    rest.getCustomer(0);
    // depending on what you do in your getCustomer method, you should check if you catched the exception, or let it pass, etc.. Make your assertions here

  public void testGetCustomer_customerNotExist() {
    // etc.
  }
}

Secara umum, setiap metode pengujian harus menguji satu hal saja, ini membantu menjaga tes Anda kecil dan fokus pada satu tugas.

Saya akan mengulanginya :-) Menulis seluruh kelas yang diejek membutuhkan waktu seperti yang Anda lihat. Pertimbangkan untuk menggunakan kerangka mengejek, semakin sedikit yang menulis kode, semakin sedikit kesalahan yang dibuat , bukan? Mengejek metode yang melempar pengecualian, atau mengembalikan nilai yang diberikan untuk parameter tertentu adalah sepotong kue dan membutuhkan 2 atau 3 baris (dengan setidaknya mockito)

Semoga itu membantu menguji metode REST Anda.

Jalayn
sumber
4
Biasanya Anda tidak memiliki logika di dalam kelas DTO Anda, terutama yang tidak berinteraksi dengan penyimpanan data Anda.
JustAnotherUserYouMayKnowOrNot
1
Itu hanya sebuah contoh, tetapi Anda benar sekali. Saya akan mengubah contoh sehingga mereka lebih sesuai dengan teori.
Jalayn