Как настроить интеграционный тест Rails для методов XML?

Учитывая метод контроллера, например:

def show
  @model = Model.find(params[:id])

  respond_to do |format|
    format.html # show.html.erb
    format.xml  { render :xml => model }
  end
end

Как лучше всего написать интеграционный тест, который утверждает, что возвращаемый результат имеет ожидаемый XML?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
12
0
5 080
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Установите заголовок принятия объектов запроса:

@request.accept = 'text/xml' # or 'application/xml' I forget which

Затем вы можете утверждать, что тело ответа совпадает с тем, что вы ожидали.

assert_equal '<some>xml</some>', @response.body

Я знаю эту часть, ищу интеграционный тест A..Z

Patrick Ritchie 12.09.2008 23:52

Этот assert_equal тоже очень хрупкий. Нет никакой гарантии порядка элементов или атрибутов; если он изменится, ваш тест сломается. Сравнение буквальных строк - неправильный способ проверки равенства XML-деревьев.

bjnord 20.08.2010 19:14

Это идиоматический способ тестирования ответа xml от контроллера.

class ProductsControllerTest < ActionController::TestCase
  def test_should_get_index_formatted_for_xml
    @request.env['HTTP_ACCEPT'] = 'application/xml'
    get :index
    assert_response :success
  end
end

Это функциональный тест, который у меня уже есть. Ищу интеграционный тест.

Patrick Ritchie 13.09.2008 19:06
Ответ принят как подходящий

Комбинация использования формата и assert_select в интеграционном тесте отлично работает:

class ProductsTest < ActionController::IntegrationTest
  def test_contents_of_xml
    get '/index/1.xml'
    assert_select 'product name', /widget/
  end
end

Для получения дополнительных сведений см. assert_select в документации Rails.

Эти 2 ответа великолепны, за исключением того, что мои результаты включают поля datetime, которые в большинстве случаев могут отличаться, поэтому assert_equal не работает. Похоже, что мне нужно будет обработать включение @response.body с помощью анализатора XML, а затем сравнить отдельные поля, количество элементов и т. д. Или есть более простой способ?

Да; поля даты и времени - еще одна причина, по которой assert_equal - неправильный способ сравнения деревьев XML. Что касается меня, я не сравнивал весь объект на равенство в своих тестах; Я использовал assert_select (как показал ntalbott выше) для конкретных атрибутов, которые хочу проверить.

bjnord 20.08.2010 19:17

Ответ от ntalbott показывает действие get. Пост-действие немного сложнее; если вы хотите отправить новый объект в виде XML-сообщения и чтобы атрибуты XML отображались в хэше params в контроллере, вы должны правильно указать заголовки. Вот пример (Rails 2.3.x):

class TruckTest < ActionController::IntegrationTest
  def test_new_truck
    paint_color = 'blue'
    fuzzy_dice_count = 2
    truck = Truck.new({:paint_color => paint_color, :fuzzy_dice_count => fuzzy_dice_count})
    @headers ||= {}
    @headers['HTTP_ACCEPT'] = @headers['CONTENT_TYPE'] = 'application/xml'
    post '/trucks.xml', truck.to_xml, @headers
    #puts @response.body
    assert_select 'truck>paint_color', paint_color
    assert_select 'truck>fuzzy_dice_count', fuzzy_dice_count.to_s
  end
end

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

(Обратите внимание также на использование to_s при сравнении целочисленного значения в assert_select.)

Другие вопросы по теме