1

ファクトリーガールとRSpecを使用してコントローラーをテストすると、次のエラーが発生します。

Failures:

  1) ProductsController Handling POST for create should redirect to products after success
     Failure/Error: response.should redirect_to(products_path)
        Expected response to be a <:redirect>, but was <200>

ログファイルに基づくと、オブジェクトはDBにすでに存在しているように見えます(そしてコントローラーのリダイレクト句を満たしていません)。これにより、2つの質問が発生します。

  1. 通話がモック/スタブされないのはなぜですか?
  2. DBをヒットしたい場合の回避策は何ですか?使用@params = FactoryGirl.build(:product).attributes.except(:id, :created_at, :updated_at)も機能しません。

どんな助けでも素晴らしいでしょう。ありがとうございました。

test.log:

Processing by ProductsController#create as HTML
Parameters: {"product"=>{"name"=>"Fruit Mania", "description"=>"The mania that is taking over the planet!", "price"=>"9.99", "inventory"=>"1", "product_image"=>"#<File:0x00
User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
Product Exists (0.1ms)  SELECT 1 AS one FROM "products" WHERE LOWER("products"."name") = LOWER('Fruit Mania') LIMIT 1

products_controller_spec.rb:

describe ProductsController, "Handling POST for create" do
  def sign_in_user
    user = FactoryGirl.create(:user)
    sign_in user, @user
  end

  def do_post
    post :create, :product => @params
  end

  before do
    @product = mock_model(Product, :save=> true)
    Product.stub!(:create).and_return(@product)
    @params = FactoryGirl.attributes_for(:product)
  end

  it "should redirect to products after success" do 
     sign_in_user
     do_post
     pending "need to figure out why redirect fails"
     response.should redirect_to(products_path)
  end
end

工場:

FactoryGirl.define do
  factory :product do
    name "Fruit Mania"
    description "The mania that is taking over the planet!"
    price "9.99"
    inventory 1
    product_image { File.open(File.join(Rails.root, 'spec', 'support', 'uploads', '1000x450.jpeg')) }
  end
end

コントローラ:

 def create
    @product = Product.new(params[:product])
    if !@product.valid?
      flash.now[:error] = ("The product was not added: <br><li>" + @product.errors.full_messages.join("<li>")).html_safe
      render "new"
    else
      if @product.save
        redirect_to products_path, :notice => "Product created successfully!"
      else
        flash.now[:error] = ("There were issues adding the product to the database. Please retry")
        render "new"
      end
    end
  end
4

1 に答える 1

1

そもそもなぜデータベース呼び出しが起こっているのかがわかります。

次の行を置き換える必要があります。

Product.stub!(:create).and_return(@product)

と:

Product.any_instance.stub!(:save).and_return(true)

クラスメソッドProduct::createをスタブ化していますが、実際にはインスタンスメソッドをスタブ化する必要がありますProduct#save

私は次のこともうまくいくと思います:

Product.stub!(:new).and_return(@product)
@product.stub(:save).and_return(true)

あなたが失敗したため、あなたが期待していた302ではなく、200のHTTP応答を与えるパスをsave通過します。render

なぜそれがデータベースにヒットしているのかについては、モデルが特定のコンテキストからすでに存在している理由を言うことができないのではないかと思います。この単一のテストのみを実行する場合、それは機能しますか?その他のアイデアについては、この質問を確認してください。

factory_girlがトランザクションで動作しないのはなぜですか?-テスト後も行はデータベースに残ります

それがお役に立てば幸いです。

于 2013-01-15T00:44:46.667 に答える