使用RSpec和Factory Girl进行模拟时获取重复项目

时间:2012-11-18 13:14:20

标签: ruby-on-rails ruby-on-rails-3 rspec rspec2 factory-bot

当使用工厂女孩和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中(并且不符合控制器中的重定向子句),这引发了两个问题:

  1. 为什么电话没有被嘲笑/抄袭?
  2. 如果我想点击数据库会有什么办法?使用@params = FactoryGirl.build(:product).attributes.except(:id, :created_at, :updated_at)也不起作用。
  3. 任何帮助都会很棒。谢谢。

    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
    

1 个答案:

答案 0 :(得分: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)

由于save失败,您需要通过render路径,该路径的HTTP响应为200,而不是您期望的302.

至于为什么它会袭击数据库,我恐怕无法说明为什么模型已经存在于给定的上下文中。如果您只运行此单一测试,它是否有效?尝试查看此问题以获取更多想法:

Why isn't factory_girl operating transactionally for me? - rows remain in database after tests

我希望有所帮助。