Заглушка named_scope в контроллере RSpec - PullRequest
2 голосов
/ 28 октября 2009

Я не смог ничего найти для такой ситуации. У меня есть модель, которая имеет именованную область видимости, определенную таким образом:

class Customer < ActiveRecord::Base
  # ...
  named_scope :active_customers, :conditions => { :active => true }
end

и я пытаюсь заглушить его в спецификации моего контроллера:

# spec/customers_controller_spec.rb
describe CustomersController do
  before(:each) do
    Customer.stub_chain(:active_customers).and_return(@customers = mock([Customer]))
  end

  it "should retrieve a list of all customers" do
    get :index
    response.should be_success
    Customer.should_receive(:active_customers).and_return(@customers)
  end
end

Это не работает и не работает, говоря, что Клиент ожидает active_customers, но получил его 0 раз. В моем фактическом контроллере для действия Index у меня есть @customers = Customer.active_customers. Чего мне не хватает, чтобы заставить это работать? К сожалению, я обнаружил, что проще написать код, чем думать о тесте / спецификации и написать, что, поскольку я знаю, что описывает спецификация, просто не могу сказать RSpec, что я хочу сделать. *

Ответы [ 3 ]

8 голосов
/ 28 октября 2009

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

Возвращаясь к вашему вопросу, есть две (или более?), Которые требуют уточнения здесь:

  1. То, что CustomersController вызывает Customer#active_customers, когда вы делаете get на index. Не имеет значения, что Customer#active_customers возвращает в этой спецификации.
  2. То, что active_customers named_scope действительно возвращает клиентов, где поле active равно true.

Я думаю, что вы пытаетесь сделать номер 1. Если это так, удалите всю заглушку и просто установите ожидание сообщения в вашем тесте:

describe CustomersController do
  it "should be successful and call Customer#active_customers" do
    Customer.should_receive(:active_customers)
    get :index
    response.should be_success
  end
end

В приведенной выше спецификации вы не проверяете, что он возвращает. Это нормально, так как это цель спецификации (хотя ваша спецификация слишком близка к реализации, а не к поведению, но это другая тема). Если вы хотите, чтобы вызов active_customers возвратил что-то конкретное, добавьте .and_returns(@whatever) к ожидаемому сообщению. Другая часть истории состоит в том, чтобы проверить, что active_customers работает должным образом (то есть: спецификация модели, которая делает фактический вызов БД).

1 голос
/ 29 октября 2009

У вас должен быть массив вокруг макета, если вы хотите проверить, что вы получаете обратно массив записей о клиентах, например:

Customer.stub_chain(:active_customers).and_return(@customers = [mock(Customer)])
0 голосов
/ 28 мая 2010

stub_chain работал лучше всего для меня.

У меня есть контроллер, вызывающий

ExerciseLog.this_user(current_user).past.all

И я могу вот так заглушить

ExerciseLog.stub_chain(:this_user,:past).and_return(@exercise_logs = [mock(ExerciseLog),mock(ExerciseLog)])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...