2016-08-04 2 views
2

Я бы хотел, чтобы тестовый пример, написанный ниже, был «чистым» тестом, который автоматически заменяет изменения базы данных после теста.Написание «чистых» интеграционных тестов - REST с использованием джерси 2 и весной

@Test 
public void testUpdate(){ 
    ClientConfig clientConfig = new ClientConfig(); 
    clientConfig.register(JacksonFeature.class); 
    Client client = ClientBuilder.newClient(clientConfig); 
    Name name = new Name(1L,"Updated","Updated"); 
    Response response = client 
      .target("http://localhost:8080/jersey-spring/name/").request().header("Content-type", MediaType.APPLICATION_JSON).post(Entity.json(name)); 
    Assert.assertTrue(response.getStatus() == 200); 
} 

Услуги по обеспечению безопасности развертываются с использованием jetty-maven-plugin во время испытаний на интеграцию. Проблема, с которой я столкнулся сейчас, заключается в том, что я не могу использовать тесты spring testtransactional, что означает, что любое изменение состояния в базе данных должно быть очищено вручную после испытаний, которые очень громоздки.

Таким образом, мой вопрос заключается в том, что является рекомендуемым подходом к проведению «чистых» интеграционных тестов при использовании jersey в качестве поставщика REST. Я также пытался использовать JerseyTest, а также сталкивался с той же проблемой.

По различным причинам я не могу заменить Джерси весной MVC.

Update

  1. Там не насмешливый участие. Тест проходит от конца до конца.
  2. Мне нравится быть рядом с производственной конфигурацией для тестов интеграции, и поэтому для интеграционных тестов не используется БД в памяти.

ответ

1

Вы не можете использовать способ обработчика REST в транзакции, которая обертывает ваш тестовый код, это просто невозможно. Однако вы можете использовать DBUnit, чтобы довести базу данных до состояния до и/или после тестирования.

Я бы рекомендовал использовать Spring Test DBUnit library из-за его фантастической интеграции с аннотациями с весной.

Кроме того, я бы рекомендовал использовать Docker для предоставления вашей базы данных, поскольку использование локальной базы данных просто не является хорошей практикой, поскольку ваш процесс сборки будет иметь внешние зависимости и потребует наличия БД на сервере CI и каждой dev-машине , Раньше я использовал Overcast, вот fine example of how to use it with Docker.

+0

Я тоже пришел к такому же выводу. Спасибо за совет докера. В нашем коде мы склонны использовать множество процедур (наследие), поэтому блок БД для меня не является вариантом. Думаю, докер + оракул - это путь. – ArunM

+1

Почему у вас есть процедуры, препятствующие использованию DBUnit? Вы должны инициализировать свою БД (процедуры включены) перед комплектом либо с помощью сценария (например, schema.sql), либо путем запуска средства миграции. После этого вы можете заполнить и проверить свои данные с помощью DBUnit. Поверьте мне, был там, сделал это :) –

3

Я использовал следующую конфигурацию для многих проектов Spring + Jersey2 и отлично работает.

  • Использование JerseyTest и продлить его в тестовом классе
  • Используйте или издеваться свои услуги в контроллере REST
  • Это важно. Используйте базу данных в памяти (я предпочитаю HSQLDB) и создаю тестовый контекст приложения, предназначенный для этого в базе данных памяти. Таким образом, вам не нужно беспокоиться о целостности данных и т. Д.
  • Настройте свой тестовый класс, переопределив configure() метод JerseyTest, вставьте свои издевательства и привяжите любые соответствующие службы вашего контроллера REST к контенту Джерси.

Вот пример:

@Override 
protected Application configure() { 
    // Bind factories of classes to be mocked. 
    AbstractBinder binder = new AbstractBinder() { 
     @Override 
     protected void configure() { 
      bindFactory(MockCrawlerManagerFactory.class).to(CrawlerManager.class); 
      bindFactory(MockUrlQueueServiceFactory.class).to(UrlQueueService.class); 
      bindFactory(MockSitemapServiceFactory.class).to(SitemapService.class); 
      bindFactory(MockCrawlerServiceFactory.class).to(CrawlerService.class); 
      bindFactory(MockUrlContentServiceFactory.class).to(UrlContentService.class); 
      // Other services to mock .... 
     } 
    }; 

    // This is your main Spring application 
    ApplicationContext context = new AnnotationConfigApplicationContext(Bootstrap.class); 

    // And create your Jersey context here, register REST controller to Jersey context 
    return new ResourceConfig().registerClasses(RestController.class, JacksonJsonProvider.class, JacksonJaxbJsonProvider.class) 
      .packages("com.company.foo.crawler.rest", "com.company.foo.crawler.exception").register(binder).property("contextConfig", context); 
} 
  • И начать писать тесты :)

Пример испытаний:

@Test 
    public void testCreateCrawlerWithNoConfiguration() throws ExecutionException, InterruptedException { 
    String mockUrl = "/version/" + VERSION + "/crawlers"; 
    Map<String, Object> data = new HashMap<>(); 
    data.put("configurationId", "null"); 
    data.put("startUrl", "http://blog.ahmetbutun.net"); 
    Future<Response> asyncRes = target(mockUrl).request(MediaType.APPLICATION_JSON_TYPE).header("userId", MOCK_CRAWLER_VALID_USER_ID).header("token", AUTHENTICATION_HEADER) 
      .async().post(Entity.json(data)); 

    RestResponse response = asyncRes.get().readEntity(RestResponse.class); 

    Assert.assertNotNull(response); 
    Assert.assertEquals(AppConstants.ERROR_CODE_INVALID_CONFIGURATION_ID_EXCEPTION, response.getStatusCode()); 
    Assert.assertEquals(HttpStatus.BAD_REQUEST.value(), response.getMessage().getStatus()); 
} 

Надежда это помогает.

+0

Спасибо за ответ. Мои тесты заканчиваются, что означает, что насмехается. Мне также нравится тестировать настоящую базу данных, поэтому я также использую локальную базу данных oracle для тестов интеграции. Проблема заключается в том, что клиентский код выполняется в отдельном потоке, поэтому он не знает о моих «тестовых» транзакциях. – ArunM

2

Просто дайте свои 2 цента. Есть конкретные вещи, которые я использую в своем стеке, поэтому это может быть только я и может не соответствовать вашему стеку. Стоит отметить, тем не менее

Я предполагаю, что вы будете использовать некоторую структуру ORM для выполнения операций с БД, когда я создаю сеансы в своих тестах, я указываю свой спящий режим на память H2 (моя конфигурация hbm на тестовой точке к Н2).

Я использую Liquibase для миграции моей базы данных, и на тестах я указываю их на эту базу данных H2 (вы можете сделать это из настройки тестов). Затем мой DAO использует эту БД для операций, здесь я могу проверить свои операции с БД и написать утверждения.

+0

Благодарю. Как я сказал ниже. Я использовал оракул. Однако реальная проблема, с которой я сталкиваюсь, заключается в том, как убедиться, что код клиента и фактический вызов останова происходят в одной транзакции? – ArunM

+1

Только для моего понимания @ArunM, вы хотите, чтобы тестовый клиент-клиент ---> [Сервер (REST API) ---> БД-логика и БД В транзакции] -> Ответ на клиента, обычно ваш тест - это ваше право клиента , Он никогда не может участвовать в транзакции на основе ресурсов на сервере? –

+0

Да, вы правы. Он никогда не может быть частью транзакции, управляемой ресурсами. Однако Spring имеет решение решить эту проблему с помощью MockMvc, я искал эквивалент трикотажа или даже взломать, что может помочь выполнить полный тест конца до конца в одной транзакции, так что мне не нужно вручную очищать базу данных после каждого теста , – ArunM

Смежные вопросы