Как настроить ассоциации моделей в тесте RSpec? - PullRequest
4 голосов
/ 03 августа 2009

Я вставил спецификации, которые я написал для представления posts / show.html.erb в приложении, которое я пишу, как средство изучения RSpec. Я все еще изучаю насмешки и окурки. Этот вопрос относится к спецификации «следует перечислить все связанные комментарии».

То, что я хочу, это проверить, что в представлении шоу отображаются комментарии к записи. Но в чем я не уверен, так это в том, как настроить этот тест и затем выполнить итерацию теста с, должен содержать ('xyz') операторы. Есть намеки? Другие предложения также приветствуются! Спасибо.

--- Edit

Еще немного информации. У меня есть named_scope, примененный к комментариям в моем представлении (я знаю, я сделал это немного назад в этом случае), так что @ post.comments.approved_is (true). Вставленный код отвечает сообщением об ошибке «неопределенный метод `mitted_is» для # », что имеет смысл, поскольку я сказал ему заглушки и вернул комментарий. Однако я все еще не уверен, как связать заглушки так, чтобы @ post.comments.approved_is (true) возвращал массив комментариев.

Ответы [ 4 ]

4 голосов
/ 12 августа 2009

Stubbing действительно путь сюда.

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

Вот пример, как я бы настроил спецификации в вашем Pastie ...

describe "posts/show.html.erb" do

  before(:each) do
    assigns[:post] = mock_post
    assigns[:comment] = mock_comment
    mock_post.stub!(:comments).and_return([mock_comment])
  end

  it "should display the title of the requested post" do
    render "posts/show.html.erb"
    response.should contain("This is my title")
  end

  # ...

protected

  def mock_post
    @mock_post ||= mock_model(Post, {
      :title => "This is my title",
      :body => "This is my body",
      :comments => [mock_comment]
      # etc...
    })
  end

  def mock_comment
    @mock_comment ||= mock_model(Comment)
  end

  def mock_new_comment
    @mock_new_comment ||= mock_model(Comment, :null_object => true).as_new_record
  end

end
1 голос
/ 03 августа 2009

Я не уверен, что это лучшее решение, но мне удалось заставить спецификацию пройти, заглушив только named_scope Буду признателен за любые отзывы по этому вопросу, а также за предложения по лучшему решению, если оно есть.

  it "should list all related comments" do
@post.stub!(:approved_is).and_return([Factory(:comment, {:body => 'Comment #1', :post_id => @post.id}), 
                                      Factory(:comment, {:body => 'Comment #2', :post_id => @post.id})])
render "posts/show.html.erb"
response.should contain("Joe User says")
response.should contain("Comment #1")
response.should contain("Comment #2")

конец

0 голосов
/ 18 марта 2011

Мне очень нравится подход Ника. У меня была такая же проблема, и я смог сделать следующее. Я верю, что mock_model тоже подойдет.

post = stub_model(Post)
assigns[:post] = post
post.stub!(:comments).and_return([stub_model(Comment)])
0 голосов
/ 04 августа 2009

Это звучит немного противно.

Вы можете сделать что-то вроде:

it "shows only approved comments" do
  comments << (1..3).map { Factory.create(:comment, :approved => true) }
  pending_comment = Factory.create(:comment, :approved => false)
  comments << pending_comments
  @post.approved.should_not include(pending_comment)
  @post.approved.length.should == 3
end

Или что-то на этот счет. В зависимости от поведения, некоторые утвержденные методы должны возвращать утвержденные комментарии к сообщению. Это может быть простой метод или named_scope. И ожидание сделало бы что-то очевидное.

У вас также может быть фабрика для: pending_comment, что-то вроде:

Factory.define :pending_comment, :parent => :comment do |p|
  p.approved = false
end

Или, если по умолчанию установлено значение false, вы можете сделать то же самое для :mitted_comments.

...