Тесты RSpec для возврата метода и наследования - PullRequest
1 голос
/ 06 июня 2019

Я пытаюсь написать два теста RSpec для двух разных задач, которые гораздо сложнее, чем я привык писать.

Что я пытаюсь проверить в моем контроллере:

def index
  @buildings ||= building_class.active.where(place: current_place)
end

Моя попытка написания теста RSpec:

describe 'GET :index' do
    it "assigns @buildings" do
      @buildings ||= building_class.active.where(place: current_place)
    get :index
    expect(assigns(:buildings)).to eq([building])
  end
end

Этот тест не прошел и даже не запустился, поэтому я знаю, что что-то упустил.


Мой второй тест должен проверить возвращаемое значение метода класса. Вот что мне нужно проверить в контроллере:

def class_name
  ABC::Accountant::Business
end

Вот моя попытка проверить этот метод:

describe "class name returns ABC::Accountant::Business" do
  subject do
    expect(subject.class_name).to eq(ABC::Accountant::Business)
  end
end

1 Ответ

0 голосов
/ 06 июня 2019

Для первого теста я бы сделал что-то вроде этого:

Во-первых, я бы переместил это .active.where(place: current_place) в область (я предполагаю, building_class возвращает Building или что-то в этом роде):

class Building << ApplicationRecord
  scope :active_in, -> (place) { active.where(place: place)

тогда заглушку для теста легче

describe 'GET :index' do
  it "assigns @buildings" do
    scoped_buildings = double(:buildings)

    expect(Building).to receive(:active_in).and_return(scoped_buildings)

    get :index
    expect(assigns(:buildings)).to eq(scoped_buildings)
  end
end

Тогда ваш контроллер будет делать

@buildings ||= building_class.active_in(current_place)

Таким образом, вы тестируете две вещи: контроллер фактически вызывает область и контроллер присваивает возвращаемое значение переменной @buildings (вам на самом деле не нужно проверять фактические компоненты, вы можете проверить область по спецификации модели).

Лично я чувствую, что было бы лучше сделать что-то вроде @buildings = current_place.active_buildings, используя ту же идею прицела, чтобы проверить, что вы получаете активные здания текущего места.


РЕДАКТИРОВАТЬ: если вы не можете модифицировать свой контроллер, то заглушка немного отличается, и это подразумевает некоторую цепочку методов, которые я не люблю явно тестировать.

scoped_buildings = double(:buildings)

controller.stub_chain(:building_class, :active, :where).and_return(scoped_building)

get :index
expect(assings(:buildings)).to eq scoped_buildings

Обратите внимание, что теперь ваш тест зависит от конкретной реализации, а реализация тестирования является плохой практикой, следует проверять поведение, а не реализацию.


Во-вторых, я думаю, что-то вроде этого должно работать:

describe ".class_name" do
  it "returns ABC::Accountant::Business" do
    expect(controller.class_name).to eq(ABC::Accountant::Business)
  end
end

ИМХО, что имя метода, если оно сбивает с толку, class_name дает представление о том, что он возвращает строку, вы не возвращаете имя, вы возвращаете класс. Может быть, вы можете изменить этот метод на resource_class или что-то менее запутанное.

...