25

几乎我遇到的每个规范文件最终都会编写如下内容:

  before :each do
    @cimg = Factory.build :cimg_valid
    @cimg.stub(:validate_img).and_return true
    @cimg.stub(:validate_img_url).and_return true
    @cimg.stub(:save_images).and_return true
    @cimg.stub(:process_image).and_return true
    @cimg.stub(:img).and_return true
  end

我的意思是,我从 Factory.build 获得的模型是完全有效的。但是,如果我不存根那些东西,它会将东西保存在文件系统中,并验证我没有测试的东西......

我的意思是,我认为做这样的事情会更干净:

  before :each do
    @cimg = Factory.build :cimg_for_testing_tags
  end

如果在工厂内存根甚至是可能的。

存根模型的正确方法是什么?

4

4 回答 4

33

@fkreusch 的答案很有效,直到您使用新的 RSpecexpect()语法(3.0+)

把它变成rails_helper.rb我的作品:

FactoryBot::SyntaxRunner.class_eval do
  include RSpec::Mocks::ExampleMethods
end

在 OP 的示例中,您现在可以执行以下操作:

FactoryBot.define do
  factory :cimg_for_testing_tags do

    ... # Factory attributes

    after(:build) do |cimg|
      allow(cimg).to receive(:validate_img) { true }
    end
  end
end

信用:github.com/printercu,见:https ://github.com/thoughtbot/factory_bot/issues/703#issuecomment-83960003

于 2015-06-30T04:16:57.427 回答
22

在最新版本的 factory_girl 中,您有一个 after_build 回调,所以我相信您可以像这样定义您的工厂:

FactoryGirl.define do
  factory :cimg_for_testing_tags do

    ... # Factory attributes

    after_build do |cimg|
      cimg.stub(:validate_img).and_return true
    end
  end
end

更新

在 factory_girl 3.3.0 之后,语法已更改为:

FactoryGirl.define do
  factory :cimg_for_testing_tags do

    ... # Factory attributes

    after(:build) do |cimg|
      cimg.stub(:validate_img).and_return true
    end
  end
end
于 2012-01-31T00:51:25.930 回答
5

工厂应该生产“真实世界”的对象,因此在工厂中改变行为(即存根)是一种不好的做法(并且容易出错)。

你可以做

let(:user) instance_double(User, FactoryGirl.attributes_for(:user))

before do
  allow(user).to receive(:something).and_return('something')
end

如果您的before子句变得太大,您可能希望将其提取到单独的方法或创建一个模拟子类来覆盖您想要存根的方法。

于 2017-09-05T15:52:41.190 回答
3

您也可以考虑使用FactoryGirl#build_stubbed

于 2014-06-06T16:28:37.773 回答