Rspec + Factory Girl(无需Rails!)

5
我正在使用selenium-webdriver gem和Rspec来测试一个Web应用程序。我希望在我的测试中包含工厂,以模拟用户并避免每次手动创建用户。
因此,我安装了factory_girl gem,并在我的spec_helper文件中添加了必要的代码行,创建了一个工厂,并在我的spec文件中包含了一些代码。但是,在运行测试时,我收到了以下错误信息: Failure/Error: FactoryGirl.build(:user) NameError: uninitialized constant User 这是我的spec_helper.rb文件:
RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
  config.expect_with :rspec do |expectations|
  expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end

我的 factories.rb 文件:

 FactoryGirl.define do
  factory :user do
    name "testuser"
    password "freestyle"
    inventory true
  end
end

我的测试规范文件:

require "json"
require "selenium-webdriver"
require "rspec"
require "factory_girl"
FactoryGirl.find_definitions
include RSpec::Expectations

describe "MallSpec" do

  before(:all) do
    FactoryGirl.build(:user)
    @driver = Selenium::WebDriver.for :firefox
    @base_url = "http://localhost:9000/"
    @accept_next_alert = true
    @driver.manage.timeouts.implicit_wait = 30
    @driver.manage.window.resize_to(1301, 744)
    @verification_errors = []
end

我的spec_file在项目的根目录中。我的factories.rb文件以及test_spec.rb文件都在/spec目录中。 有人能帮我解决这个问题或指出我做错了什么吗?


在您的应用程序上下文中,“用户”是什么? - user229044
2个回答

2
如果您实际上没有一个User类,但您想使用FactoryGirl生成属性,则可以覆盖该类:
require "ostruct"

FactoryGirl.define do
  factory :user, class: OpenStruct do
    name "testuser"
    password "freestyle"
    inventory true

    # This isn't necessary, but it will prevent FactoryGirl from trying
    # to call #save on the built instance.
    to_create {}
  end
end

如果你只需要一个Hash,可以使用attributes_for,如果你需要一个响应像name这样的方法的对象,则可以使用create

如果你想生成用于API的JSON,可以使用像Hashie::Mash这样的库:

factory :user, class: Hashie::Mash do
  # ...
end

# In your tests:
user_json = create(:user).to_json

非常感谢,我现在会尝试这个,并稍后在这里发布结果! - Alexandra Kalm

1
当运行测试时,我收到一个错误Failure/Error: FactoryGirl.build(:user) NameError:未初始化常量User。
您的用户类必须被定义。以下是一个没有定义User类的测试:
require 'factory_girl' 

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end

FactoryGirl.define do 
  factory :user do 
    name 'Alice'
    age 10
  end
end

describe "MallSpec" do
  let(:test_user) { FactoryGirl.build(:user) }

  describe "user's name" do
    it "equals 'Alice'" do
      expect(test_user.name).to eq('Alice')
    end
  end

end

--output:--
$ rspec 1.rb 
F

Failures:

  1) MallSpec user's name equals 'Alice'
     Failure/Error: let(:user) { FactoryGirl.build(:user) }
     NameError:
       uninitialized constant User
...

添加一个对 User类 的定义:
require 'factory_girl' 

#====NEW CODE=====
class User
  attr_accessor :name, :age
end
#=================

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end

FactoryGirl.define do 
  factory :user do 
    name 'Alice'
    age 10
  end
end

describe "MallSpec" do
  let(:test_user) { FactoryGirl.build(:user) }

  describe "user's name" do
    it "equals 'Alice'" do
      expect(test_user.name).to eq('Alice')
    end
  end

end

--output:--
$ rspec 1.rb 
.

Finished in 0.0024 seconds (files took 0.35197 seconds to load)
1 example, 0 failures

我预计这里的factory()方法是:
  factory :user do 
    name 'Alice'
    age 10
  end

"类似于这样的操作:..."(保留HTML标签)
def factory(model_name)
   target_class = constant_get(model_name.capitalize)

为了构建User类的真实实例。换句话说,factory_girl构建已经存在于您的应用程序中的类的实例——factory_girl不会模拟一个类。

谢谢您的回答,这对我很有帮助。我以为Factory Girl模拟的是一个用户类本身。我们的后端是用PHP编写的,而不是ruby,前端客户端接收到的是JSON格式的数据。因此,我需要重新考虑我的rspec测试方法。 - Alexandra Kalm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接