这个rspec失败代码有什么问题

时间:2015-12-01 12:03:46

标签: rspec

这是我在这里的第一个问题,我实际上是在问,因为我很绝望而且我的课程导师已经离开...我正在关注网络开发课程,并在使用RSpec进行单元测试时遇到了这个问题。我正在使用的命令行是rspec spec / models(该文件夹中的文件是:product_spec.rb)。这是我用来测试的代码:

    require 'rails_helper'

    describe Product do

        context "when the Product has comments" do

            before do
                @product = Product.create(:name => "product model")
            end
        end

        context "when user has email & password" do

            before do
                @user = User.create(:email => "testspec@test.com", :password => "passtheword")
            end
        end



    context "create comment 1" do

        before do
            @product.comments.create(:rating => 1, :user => @user, :body => "Awful comment!")
        end
    end

    context "create comment 2" do

        before do
            @product.comments.create(:rating => 3, :user => @user, :body => "another awful comment!")
        end
    end

    context "create coment 3" do

        before do
            @product.comments.create(:rating => 5, :user => @user, :body => "yet another awful comment!")
        end
    end

    context "rating average" do
        before { @average_rating = Product.comments.count(:rating) }
        it "returns the average rating" do
            expect(@average_rating).to eq 3
        end
    end

    end

这是我从RSpec获得的错误:

    F

    Failures:

      1) Product rating average returns the average rating
         Failure/Error: before { @average_rating = Product.comments.count(:rating) }

 NoMethodError:
   undefined method `comments' for #<Class:0x007fe22e58b6d8>
 # ./spec/models/product_spec.rb:43:in `block (3 levels) in <top (required)>'

Finished in 0.00099 seconds (files took 1.61 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/models/product_spec.rb:44 # Product rating average returns the average rating

我甚至尝试将'评论'声明为:

context "register comment" do
  before do
    @comments = @product.comments
  end
end

但这没有任何区别。任何有关此事的帮助都会非常感激,因为我疯了,过去3天在电脑附近砸东西!接下来就是粉碎电脑本身! 非常感谢阅读。希望你过得愉快。

1 个答案:

答案 0 :(得分:0)

如果不了解您的域名,模型关联等,很难真正清楚。但是,这里的主要问题似乎是使用上下文块。

在每个上下文块context "create comment 1" do中设置上下文,使用before块设置测试,然后关闭上下文块。这些块中的每一个都是彼此不同的,因为它们当前编写的目的没有任何意义 - 因为没有任何期望在其中任何一个中进行测试。

context "rating average" do
  ##This sets up your test within this context block.
  before do
    Product.comments.create(:rating => 1, :user => @user, :body => "Awful comment!")
    Product.comments.create(:rating => 3, :user => @user, :body => "another awful comment!")
    Product.comments.create(:rating => 5, :user => @user, :body => "yet another awful comment!")
  end

   ##Now lets test it.
   let(:average_rating) { Product.comments.count(:rating) }

   it "returns the average rating" do
     expect(average_rating).to eq 3
   end
end

代码可能不正确,但应更清楚地显示您希望如何构建测试。你可能需要进一步调整它。

以下代码采用类似于餐馆和评论的示例,可以比作产品和评论/评级:

##In this example we need to create some users to create our restaurants and then reviews so use RSpec's ```let``` which is lazily evaluated.
let(:user) { User.create(email: "test@test.com", password: "password" }
let(:user2) { User.create(email: "test2@test.com", password: "passwordpass2" }

##Then we test (and also set up the conditions within the test itself).
context '1 review' do
  it 'returns that rating' do
    restaurant = user.restaurants.create(name: 'BK Lounge')
    restaurant.build_review({"thoughts" => "Great!", "rating" => 4}, user).save
    expect(restaurant.average_rating).to eq 4
  end
end

context 'multiple reviews' do
  it 'returns the average' do
    restaurant = user.restaurants.create(name: 'BK Lounge')
    restaurant.build_review({"thoughts" => "Not great!", "rating" => 1}, user).save
    restaurant.build_review({"thoughts" => "Great!", "rating" => 5}, user2).save
    expect(restaurant.average_rating).to eq 3
  end
end

值得注意的是,这些测试可能会被letbefore严重重构,甚至使用FactoryGirl之类的工具来创建测试对象,但是应该提供解决问题的有用示例。

希望这会有所帮助。