RSpec没有加载ControllerMacros方法

时间:2013-11-24 12:49:18

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

我添加了ControllerMacro但该方法未在我的规范中提供。我的规格将失败:

NoMethodError: undefined method `attributes_with_foreign_keys' for FactoryGirl:Module

我正在尝试在Github上进行this讨论之后这样做。我查看了other个类似的问题,但大多数人指的是使用config.include ControllerMacros, :type => :controller代替config.extend ControllerMacros, :type => :controller我已经在做的事情。

现在我知道在开始测试时正在加载controller_macros.rb文件,因为我通过RubyMine的调试器运行了规范,但为什么这个方法不可用超出我的范围!

spec_helper.rb

require 'simplecov'
SimpleCov.start 'rails'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'email_spec'
require 'rspec/autorun'

Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|
  config.include(EmailSpec::Helpers)
  config.include(EmailSpec::Matchers)
  config.include ControllerMacros, :type => :controller

  config.include FactoryGirl::Syntax::Methods

  config.use_transactional_fixtures = true

  config.infer_base_class_for_anonymous_controllers = false

  config.order = "random"

  config.before(:suite) do
    DatabaseCleaner.strategy = :truncation
  end
  config.before(:each) do
    DatabaseCleaner.start
  end
  config.after(:each) do
    DatabaseCleaner.clean
  end
end

spec/support/macros/controller_macros.rb

module ControllerMacros
  def attributes_with_foreign_keys(*args)
    FactoryGirl.build(*args).attributes.delete_if do |k, v|
      ["id", "type", "created_at", "updated_at"].member?(k)
    end
  end
end

此示例控制器规范:

describe "POST create" do
  describe "with valid params" do
    it "creates a new Course" do
      expect {
        #post :create, course: FactoryGirl.build(:course)
        post :create, course: FactoryGirl.attributes_with_foreign_keys(:course)
      }.to change(Course, :count).by(1)
    end

2 个答案:

答案 0 :(得分:1)

失败的原因:

您定义的宏是模块中的方法。您要求Rspec包含该模块,因此该方法可用于Rspec的实例,该实例应与describeit等类似。

但是,您将此方法用作FactoryGirl的类方法。显然这不起作用。

解决方案。

在特殊情况下,您希望有一种方便的方法来快速构建模型的一组预定义属性。

这种逻辑最好不要成为“宏”,因为最好将FactoryGirl用作存储模型所有逻辑的集中位置。

因此,最方便的方法是,在正常工厂之外,为这种情况定义一个特殊的工厂,比如foo,其中包含您需要的所有关联和其他逻辑,并从其他正常工厂继承。< / p>

如果名称为foo,那么您可以轻松构建foo属性的哈希值,如FactoryGirl.attributes_for :foo

答案 1 :(得分:1)

而不是打电话:

post :create, course: FactoryGirl.attributes_with_foreign_keys(:course)

请致电:

post :create, course: attributes_with_foreign_keys(:course)

从@Billy Chan的回答中得到建议。