rspec тестирование ассоциации - PullRequest
8 голосов
/ 24 марта 2011

Я хочу проверить, связан ли сотрудник с компанией в моих тестах контроллера rspec.

Я хотел бы закончить с этим в моем create действии штатного диспетчера:

staff.companies << current_company

Где current_company собирается из переменной сеанса.

Как мне написать тест для этого?

У меня есть эти модели

class Company < ActiveRecord::Base
  has_many :employees
  has_many :staff, :through => :employees
end

class Employee < ActiveRecord::Base
  belongs_to :company
  belongs_to :staff
end

class Staff < ActiveRecord::Base
  has_many :employees
  has_many :companies, :through => :employees
end

Следующий тест - это моя попытка определить ассоциацию, и она не проходит, когда я ввожу код ассоциации:

    it "should belong to the current_company" do
      staff.should_receive(:companies)
      post :create
    end

Если я ввожу код «staff.companies << current_company» в моем контроллере, я получаю эту ошибку при запуске этого теста: </p>

 Failure/Error: post :create
 NoMethodError:
   You have a nil object when you didn't expect it!
   You might have expected an instance of Array.
   The error occurred while evaluating nil.<<

Метод создания штатного контроллера:

  def create
    @staff = Staff.new(params[:staff])

    if @staff.save
      @staff.companies << current_company
      redirect_to staff_index_path, :notice => "Staff created successfully!"
    else
      @company = @staff.firm || current_company
      flash[:alert] = "Staff failed to create"
      render "new"
    end
  end

Ответы [ 4 ]

14 голосов
/ 24 мая 2011

Я бы использовал другой подход, поскольку проверка того, что модель должна получить определенное сообщение, слишком тесно связывает ваши тесты с реализацией. Вас действительно волнует, получает ли компания #<< или какой-либо другой метод?

Действительно, вы хотите проверить, зарегистрирована ли компания пользователя при публикации на странице. Не имеет значения как было записано. Поэтому я бы сделал что-то вроде этого:

it "should add the company to the user's list of companies" do
  lambda do 
    post :create
  end.should change(staff.companies, :count).from(0).to(1)
  staff.companies.map(&:name).should include("Acme, Inc.")
end

Это тестовое поведение вместо реализации. Преимущество состоит в том, что ваш тест не пройдёт, если кто-то изменит это << на эквивалентное push Кроме того, у него есть ясность в отношении ваших намерений и, следовательно, лучшее документирование кода.

2 голосов
/ 23 мая 2011

Если вы находитесь в спецификации вашего контроллера, я бы использовал stub_chain

staff.stub_chain(:company, :<<).once.and_return(true)

, который будет имитировать вызов компании И вызов << И ожидать, что он будет вызван один раз. </p>

(по крайней мере, .once должен работать с stub_chain ...)

1 голос
/ 25 мая 2011

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

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

Затем, когда вы пытаетесь поместить компанию в этот новый, нулевой метод, используя <<, он говорит, что не может этого сделать. </p>

Чтобы обойти это, вы можете сделать то, что сделали, то есть установить возвращаемое значение.:

staff.should_receive(:companies).and_return([])

, который затем удостоверится, что:

@staff.companies << current_company

не потерпит неудачу с ужасной ошибкой nil (потому что есть и реальный, реальный массив для компании, в который нужно войти).

Но на самом деле лучшее, что можно сделать, это как предлагали предыдущие люди, и протестировать то, что вам действительно нужно протестировать - то есть, что спасение персонала в компаниях приведет к тому, что новая компания будет сохранена в БД.

1 голос
/ 19 мая 2011

Вы можете проверить это с помощью:

staff.should have(1).company

Или, если у персонала уже есть другие компании, получите счет и проверьте наличие (количество + 1) .companies.

...