Как я могу протестировать мой веб-сервис REST?

16

Я новичок в модульном тестировании, у меня есть один веб-метод REST, который просто вызывает DB и заполняет DTO. Псевдокод

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

Я сомневаюсь, как написать тесты для этих методов и типы тестов (интеграция / модуль), которые будут включены. А для юнит-тестов нужно ли попадать в БД. Если это так, и я передаю идентификатор клиента и делаю несколько утверждений, данные могут измениться, что в итоге приведет к сбоям.

Я думаю, что я чего-то здесь не понимаю, понимая эти понятия.

Солнечный
источник
5
В опубликованном вами коде необходимо протестировать следующее: (1) Можете ли вы вызвать GetCustomer с int в качестве параметра. (2) Возвращает ли он объект CustomerDTO? (3) Заполнен ли этот объект из БД, как и ожидалось. (4) Происходит ли ожидаемое поведение при вызове с int, который не соответствует действительному клиенту? Ничто из этого не имеет отношения к REST. Когда вы будете готовы написать код, который отвечает на запросы RESTful, вы напишите тесты для него.
DavidO
@DavidO: «Заполнен ли этот объект из БД, как и ожидалось». это определенно не модульный тест (в отношении кода OP). Это интеграционный тест.
Флэтер
Да вы правы. Если бы я мог вернуться и изменить комментарий, упомянув, что в интеграционном тесте вы проверили бы компонент БД, и в противном случае смоделировали бы его, я сделал бы это редактирование, но окно редактирования для комментариев, если 5 минут, и комментарий был сделан шесть много лет назад. :)
DavidO

Ответы:

18

Во время модульного тестирования от вас не ожидается тестирования с базой данных или, по крайней мере, с базой данных, которую вы не подготовили для модульного тестирования. Тестирование с использованием базы данных и, следовательно, одновременное тестирование различных уровней вашего приложения обычно рассматривается как интеграционные тесты . С помощью модульных тестов вы должны тестировать только то, что делает ваш метод, что он возвращает в зависимости от различных параметров, и когда (или нет) он должен потерпеть неудачу.

Очень ожидаемо, что в вашем методе вы делаете вызовы методов X из других классов. Вы не испытывать эти X методов так , что вы должны сделать , это высмеивать эти методы.

Я предполагаю, что вы пишете свой код на Java, в этом случае у вас есть отличные фреймворки, такие как Mockito, которые могут быть вам полезны. Независимо от того, используете ли вы фреймворк или нет, я просто скажу, что они сэкономят вам много времени, и тот, который я упомянул, по крайней мере, не сложен.

Если вы просто хотите написать свой собственный макет для эксперимента, то предположим, что у вас есть следующий CustomerRepositoryкласс:

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

Вы можете написать свой собственный издевательский и грязный CustomerRepositoryкласс следующим образом:

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

Затем в вашем тестовом примере вы в основном заменяете свой «стандартный» экземпляр CustomerRepositoryна макетированный экземпляр, который позволит вам протестировать ваш метод для различных результатов 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.
  }
}

Как правило, каждый метод тестирования должен проверять только одну вещь, это помогает сделать ваши тесты небольшими и сфокусированными на одной задаче.

Я собираюсь повторить это :-) Как вы видите, написание целого издевательского класса занимает некоторое время. Подумайте об использовании фальшивого фреймворка: чем меньше вы пишете код, тем меньше ошибок делаете , верно? Насмешка над методом, который выдает исключение или возвращает заданное значение для заданного параметра, - это кусок пирога и занимает 2 или 3 строки (по крайней мере, с mockito)

Надеюсь, это поможет проверить ваш метод REST.

Jalayn
источник
4
Обычно у вас нет логики в ваших классах DTO, особенно те, которые взаимодействуют с вашим хранилищем данных.
JustAnotherUserYouMayKnowOrNot
1
Это был просто пример, но ты абсолютно прав. Я собираюсь изменить примеры, чтобы они лучше соответствовали теории.
Джалайн