上一篇我们介绍了factory-girl,这是一个很好的工具,可以用来替代rails中的fixtures,用来生成模拟数据。
它直观,易读,易读就易维护。最重要的一点是,它是面向model的,面向业务的,面向应用的,而fixtures模拟的数据是面向数据库的。但是我们的单元测试,功能测试,甚至将来要介绍的集成测试,都是面向业务的,从业务角度出发的测试,测试系统是否满足业务需求。所以好处显而易见了,相信大家在使用了以后会有一点感触。
上篇我们介绍了一些基本的使用,创建单个model的模拟对象,填充属性的值。
- FactoryGirl.define do
- factory :user_valid, :class => :User do
- nickname "nickname"
- email "[email protected]"
- password "123"
- password_confirmation "123"
- end
- factory :user_invalid_password_do_not_match, :class => :User do
- nickname "nickname2"
- email "[email protected]"
- password "1232"
- password_confirmation "123"
- end
- end
上面模拟了两个user对象,一个有效的,一个无效的(因为密码不匹配)。
通过
- user = FactoryGirl.build(:user_valid)
就可以访问到factory-girl模拟的数据,进而在单元测试及功能测试中使用这些模拟的数据。
但是有时候我们有更高的要求,比如说我们的实体是有关系的,has_many,belongs_to,has_and_belongs_to_many等等。是否能在创建model的同时,也创建它的关联实体?答案是:可以。
举一个简单的关系吧。就拿我的blog项目。
post和category,一个post属于一个category,一个category包含多个post。
- class Post < ActiveRecord::Base
- belongs_to :category
- end
- class Category < ActiveRecord::Base
- has_many :posts
- end
我们可以像下面这样做。
- FactoryGirl.define do
- factory :category do
- title "category"
- end
- factory :category_valid, :class=>:Category do
- title "categorytitle"
- end
- end
- FactoryGirl.define do
- factory :post_valid_with_category1, :class => :Post do
- title "post"
- slug "slug"
- summary "summary"
- content "content"
- category
- end
- factory :post_valid_with_category2, :class => :Post do
- title "post"
- slug "slug"
- summary "summary"
- content "content"
- association :category, :factory => :category_valid
- end
- end
上面显示我们用两种方式模拟了两个category,两个post,并且在post中指定了对应的category。
- build(:post_valid_with_category1).category.title="category"
- build(:post_valid_with_category1).category.title="categorytitle"
我们可以像上面这样使用,就可以访问到post模拟对象的category模拟对象。
还有一种办法,利用alias别名。
假设我们的user和post和commenter是下面的关系。
- class User < ActiveRecord::Base
- attr_accessible :first_name, :last_name
- has_many :posts
- end
- class Post < ActiveRecord::Base
- attr_accessible :title
- belongs_to :author, :class_name => "User", :foreign_key => "author_id"
- end
- class Comment < ActiveRecord::Base
- attr_accessible :content
- belongs_to :commenter, :class_name => "User", :foreign_key => "commenter_id"
- end
你就可以像下面这样创建模拟数据。
- factory :user, aliases: [:author, :commenter] do
- first_name "John"
- last_name "Doe"
- end
- factory :post do
- author
- # instead of
- # association :author, factory: :user
- title "How to read a book effectively"
- end
- factory :comment do
- commenter
- # instead of
- # association :commenter, factory: :user
- content "Great article!"
- end
使用alias别名,给user对象起了两个别名,一个给post用,一个给comment用。别名分别对应于post和comment的两个属性。
参考文献
1.factory-girl getting started