我对编程,Rails,Ruby,Rspec等都比较陌生,所以感谢您的帮助!
我的规格很重复,所以我写了一些规范帮助方法。我无法弄清楚如何在我的规格中正确使用它们。具体来说,我有一个带有create:
的用户控制器 def create
@user = User.new(params[:user])
if @user.save
redirect_to user_path(@user)
else
render :action => :new
end
end
创建有效用户的规范助手中的一点:
def valid_user_eilif
@test_image = Rails.root + "spec/fixtures/images/seagull.jpg"
@file = Rack::Test::UploadedFile.new(@test_image, "image/jpeg")
user = User.create!(:username => "eilif", :email => "eilif@email.org",
:image => @file, :bio => "Lots of text that I don't want to write",
:signature_quote => "Yet more text.")
user.save!
user
end
然后在我的用户控制器规范中:
before (:each) do
post :create, :user => valid_user_eilif
end
it 'should assign user to @user' do
assigns(:user).should eq(User.last)
end
当我运行规范时,我收到错误:
Failure/Error: assigns(:user).should eq(User.last)
expected #<User id: 1, username: "eilif", email: "eilif@email.org", bio: "Lots of text that I don't want to write", signature_quote: "I feel empty.", image_file_name: "seagull.jpg", image_content_type: "image/jpeg", image_file_size: 10475, image_updated_at: "2011-05-10 23:35:55", created_at: "2011-05-10 23:35:56", updated_at: "2011-05-10 23:35:56">
got #<User id: nil, username: nil, email: nil, bio: nil, signature_quote: nil, image_file_name: nil, image_content_type: nil, image_file_size: nil, image_updated_at: nil, created_at: nil, updated_at: nil>
所以,我认为我错误地发布创建,因为什么都没有创建?这样做的正确方法是什么?
答案 0 :(得分:1)
理想情况下,控制器规范不应该依赖于能够在数据库中创建行的模型。通过这么简单的操作,您可以模拟出依赖关系:
describe UsersController do
context "on success" do
before(:each) do
@user = mock_model(User,:save=>true)
User.stub(:new) {@user}
post :create, :user => {}
end
it "redirects" do
response.should redirect_to(user_path(@user))
end
it "assigns" do
assigns[:user].should == @user
end
end
context "on failure" do
it "renders 'new'" do
@user = mock_model(User,:save=>false)
User.stub(:new) {@user}
post :create, :user => {}
response.should render_template "users/new"
end
end
end
请注意,规范不会传递params[:user]
中的任何内容。这有助于强制关注的MVC分离,由此模型负责处理属性,即。验证,设置关联等等。你不能总是把控制器保持为“瘦”,但尝试一下是个好主意。
答案 1 :(得分:0)
看起来问题是保存后@user
没有刷新。试试assigns(:user).reload.should eql(User.last)
。
但还有一个小问题,那可能还是会失败。您不应该使用post
致电:user => valid_user_eilif
;您希望用户记录中的属性,而不是实际的用户对象本身。而你实际上是在valid_user_eilif
中创建一个新用户,然后让你的控制器再次创建该对象 - 如果你有任何一种独特的约束,你就会发生冲突。
这是使用factory_girl和模拟等内容的好地方。例如,take a look表示我的一个项目如何处理控制器规范。此示例使用factory_girl,Mocha和shoulda。我将用下面的评论对其进行注释:
describe MembersController, "POST create" do
before do
# Factory Girl - builds a record but doesn't save it
@resource = Factory.build(:member)
# Mocha expectation - overrides the default "new" behavior and makes it
# return our resource from above
Member.expects(:new).with({}).returns(@resource)
# Note how we expect it to be called with an empty hash; that's from the
# `:member` parameter to `post` below.
end
context "success" do
before do
post :create, :member => {}
end
# shoulda matchers - check for a flash message and a redirect
it { should set_the_flash.to(/successfully created/) }
it { should redirect_to(member_path(@resource)) }
end
context "failure" do
before do
# Mocha - To test a failing example in the controller, we override the
# default `save` behavior and make it return false, otherwise it would
# be true
@resource.expects(:save).returns(false)
post :create, :member => {}
end
# shoulda matchers - check for no flash message and re-render the form
it { should_not set_the_flash }
it { should render_template(:new) }
end
end