【发布时间】:2014-07-16 14:05:07
【问题描述】:
我最近学习了如何在 rspec 中存根,发现它的一些好处是我们可以解耦代码(例如控制器和模型),更高效的测试执行(例如存根数据库调用)。
但是我认为,如果我们存根,代码可以与特定实现紧密绑定,因此牺牲了我们以后重构代码的方式。
例子:
用户控制器
# /app/controllers/users_controller.rb
class UsersController < ApplicationController
def create
User.create(name: params[:name])
end
end
控制器规格
# /spec/controllers/users_controller_spec.rb
RSpec.describe UsersController, :type => :controller do
describe "POST 'create'" do
it 'saves new user' do
expect(User).to receive(:create)
post :create, :name => "abc"
end
end
end
这样做我不只是将实现限制为仅使用User.create吗?因此,稍后如果我更改代码,即使两个代码的目的相同,即将新用户保存到数据库,我的测试也会失败
# /app/controllers/users_controller.rb
class UsersController < ApplicationController
def create
@user = User.new
@user.name = params[:name]
@user.save!
end
end
如果我在没有存根的情况下测试控制器,我可以创建一个真实的记录,然后检查数据库中的记录。只要控制器能够保存用户 Like so
RSpec.describe UsersController, :type => :controller do
describe "POST 'create'" do
it 'saves new user' do
post :create, :name => "abc"
user = User.first
expect(user.name).to eql("abc")
end
end
end
如果代码看起来不正确或有错误,我真的很抱歉,我没有检查代码,但你明白我的意思。
所以我的问题是,我们可以模拟/存根而不必绑定到特定的实现吗?如果是这样,请您在 rspec 中举个例子
【问题讨论】:
标签: ruby-on-rails ruby testing rspec tdd