使用rspec,devise,guard和spork时,无法在工厂女孩中创建用户工厂

时间:2012-08-10 03:39:37

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

我已经在几个地方看到过这个问题,但是没有一个解决方案似乎有效。

我有一个Rails 3.1应用程序,包含最新版本的guard,spork,factory girl,rspec和devise。

每当我尝试创建用户工厂(用户模型是设计模型)时,我都会收到此错误:

Could not find a valid mapping for #<User...model attributes...>

我不确定问题是什么。

我跑了rake db:test:prepare。我按照此stackoverflow问题中的说明进行操作:"Could not find a valid mapping for #<User ...>" only on second and successive tests

另外,我尝试了谷歌小组的答案中的解决方案:

https://groups.google.com/forum/?fromgroups#!topic/plataformatec-devise/StpbEsDCec0[1-25]

而且,以下是所有相关代码:

Guardfile

    # A sample Guardfile
# More info at https://github.com/guard/guard#readme
require 'capybara/rspec'
guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' }, :rspec_env => { 'RAILS_ENV' => 'test' } do
  watch('config/application.rb')
  watch('config/environment.rb')
  watch('config/environments/test.rb')
  watch(%r{^config/initializers/.+\.rb$})
  watch('Gemfile')
  watch('Gemfile.lock')
  watch('spec/spec_helper.rb') { :rspec }
  watch('test/test_helper.rb') { :test_unit }
  watch(%r{features/support/}) { :cucumber }
end

guard 'rspec', :version => 2, :cli => '--drb' do
  watch(%r{^spec/.+_spec\.rb$})
  watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
  watch('spec/spec_helper.rb')  { "spec" }

  # Rails example
  watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
  watch(%r{^app/(.*)(\.erb|\.haml)$})                 { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
  watch(%r{^spec/support/(.+)\.rb$})                  { "spec" }
  watch('config/routes.rb')                           { "spec/routing" }
  watch('app/controllers/application_controller.rb')  { "spec/controllers" }

  # Capybara request specs
  watch(%r{^app/views/(.+)/.*\.(erb|haml)$})          { |m| "spec/requests/#{m[1]}_spec.rb" }

  # Turnip features and steps
  watch(%r{^spec/acceptance/(.+)\.feature$})
  watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$})   { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
end
</code>

This is in my spec/factories.rb

FactoryGirl.define do   
 load "#{Rails.root}/app/models/user.rb"  
 factory :user, class: User do |user|
    email 'owner@example.com'
     password '12345678'
    password_confirmation '12345678'
     companyid 'example_company'   
  end 
end

This is my spec/controllers/api_controller_spec.rb

require 'spec_helper'

describe ApiController do
  it 'verifies company_id through POST to api/company_id' do
    load "#{Rails.root}/app/models/user.rb"
    debugger
    user = FactoryGirl.create(:user)
    post(:get_company_id, {:company_id => 'example_company'})
    response.body.should include('true')
  end
end

And I have this at the end of my config/application.rb

    ActionDispatch::Callbacks.after do
  # Reload the factories
  return unless (Rails.env.development? || Rails.env.test?)

  unless FactoryGirl.factories.blank? # first init will load factories, this should only run on subsequent reloads
    FactoryGirl.factories.clear
    FactoryGirl.find_definitions
  end
end

I'm really desperate for an answer here because otherwise I won't be able to test my User model (which is the most important model I have).

Feel free to comment and ask any questions.

EDIT: code looked funny in places, so I edited it for clarity

UPDATE:

So I tried simplifying everything to get to the core of the problem, and I'm pretty sure that devise and factory girl don't "like" each other. I'm still getting the exact same error whenever I try and create a user factory.

This is my new setup (I reverted to a previous git commit and I no longer have guard or spork).

My factories.rb is exactly the same as Michael Durant's except I have an extra line:

companyid 'example'

That's just a requirement for my app.

My spec_helper.rb requires rubygems and capybara/rspec and that's it.

And this is my spec/models/user_spec.rb

require 'spec_helper'
  describe 'User associations' do

    it 'tests creation of user' do
      debugger
      user = FactoryGirl.create(:user)
      User.count.should be(1)

    end
  end

Also, this is interesting: When I hit that debugger statement and type in

 eval User

It shows the mapping of a valid User.

UPDATE:

So, it's not factory girl that's the problem. It's devise.

This is the new api_controller_spec.rb file and it comes up with the same error of not having a valid mapping of the user.

require 'spec_helper'

    # A sample Guardfile
# More info at https://github.com/guard/guard#readme
require 'capybara/rspec'
guard 'spork', :cucumber_env => { 'RAILS_ENV' => 'test' }, :rspec_env => { 'RAILS_ENV' => 'test' } do
  watch('config/application.rb')
  watch('config/environment.rb')
  watch('config/environments/test.rb')
  watch(%r{^config/initializers/.+\.rb$})
  watch('Gemfile')
  watch('Gemfile.lock')
  watch('spec/spec_helper.rb') { :rspec }
  watch('test/test_helper.rb') { :test_unit }
  watch(%r{features/support/}) { :cucumber }
end

guard 'rspec', :version => 2, :cli => '--drb' do
  watch(%r{^spec/.+_spec\.rb$})
  watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
  watch('spec/spec_helper.rb')  { "spec" }

  # Rails example
  watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
  watch(%r{^app/(.*)(\.erb|\.haml)$})                 { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
  watch(%r{^spec/support/(.+)\.rb$})                  { "spec" }
  watch('config/routes.rb')                           { "spec/routing" }
  watch('app/controllers/application_controller.rb')  { "spec/controllers" }

  # Capybara request specs
  watch(%r{^app/views/(.+)/.*\.(erb|haml)$})          { |m| "spec/requests/#{m[1]}_spec.rb" }

  # Turnip features and steps
  watch(%r{^spec/acceptance/(.+)\.feature$})
  watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$})   { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
end
</code>

这对任何其他环境都不是问题,因为我可以通过控制台创建用户,同时运行本地服务器,或者将代码推送到Heroku。它可能是rspec或其他东西,但我现在还不确定。

2 个答案:

答案 0 :(得分:2)

我建议你简化一些事情来找到问题。目前我觉得你有太多的变数或太多可变因素。

我会推荐以下内容:

1建立一个新分支。我假设您正在使用git,如果不使用它(git init)并生成一个fork。

2取下所有的叉子和护罩。它们有助于加速测试并在CI(持续集成)中运行测试,但它们肯定不是“需要”,删除它们将有助于发现真正的问题。

3正确设置用户工厂。我们用这个:

FactoryGirl.define do
  sequence :email do |n| 
    "email#{n}@factory.com"
  end 

  factory :user do
    email 
    first_name            { 'First' }
    last_name             { 'Last' }
    password              { "password" }
    password_confirmation { "password" }
    association           :area
    role                  { 'super_user' }
  end 

end

4正确设置spec_help。 我们在spec_helper.rb中使用这些要求:

require 'rubygems'
require 'capybara/rspec'

5尝试使用spec / models / user_spec.rb来传递一个用户测试,例如:

require 'spec_helper'
describe 'User associations' do
subject { User.new }
it { should validate_presence_of :area }
...

答案 1 :(得分:1)

所以,答案与后卫,spork,rspec或factory_girl无关。

问题在于,我对我的devise_for :users路线进行了注释,因为我一直在对我的rails应用进行大规模的改造。

这总是愚蠢的简单&gt;。&lt;