Ruby-on-rails Rspec:控制器中的存根方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17918430/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rspec: Stub method that is in the controller
提问by shoujo_sm
May I know how to stub method that is in the controller create method? I need to write the spec for this but I got these errors. I need to check the create method in controller must execute validate_fbid method before create a new company record in model.
我可以知道如何存根控制器创建方法中的方法吗?我需要为此编写规范,但我遇到了这些错误。在模型中创建新公司记录之前,我需要检查控制器中的 create 方法必须执行 validate_fbid 方法。
Error:
错误:
1) Companies new company create with valid information#validate_fbid should have correct parameters and return value
Failure/Error: CompaniesController.create.should_receive(:validates_fbid).with(company)
NoMethodError:
undefined method `create' for CompaniesController:Class
# ./spec/requests/companies_spec.rb:38:in `block (5 levels) in <top (required)>'
2) Companies new company create with valid information#validate_fbid should fbid validation passed
Failure/Error: CompaniesController.create.stub(:validates_fbid).and_return('companyid')
NoMethodError:
undefined method `create' for CompaniesController:Class
# ./spec/requests/companies_spec.rb:43:in `block (5 levels) in <top (required)>'
CompaniesController
公司控制器
def create
company = Company.new(params[:company])
verifyfbid = validate_fbid(company)
if verifyfbid != false
if company.fbid.downcase == verifyfbid.downcase
if company.save
@message = "New company created."
redirect_to root_path
else
@message = "Company create attempt failed. Please try again."
render 'new'
end
else
@message = "Company create attempt failed. Invalid facebook id."
render 'new'
end
else
@message = "Company create attempt failed. No such facebook id."
render 'new'
end
end
private
def validate_fbid(company)
uri = URI("http://graph.facebook.com/" + company.fbid)
data = Net::HTTP.get(uri)
username = JSON.parse(data)['username']
if username.nil?
return false
else
"#{username}"
end
end
Requests/companies_spec.rb
请求/companys_spec.rb
context "#validate_fbid" do
#validate fbid
let(:company){ Company.new(name:'Example Company', url: 'www.company.com', fbid: 'companyid', desc: 'Company desc' )}
it "should have correct parameters and return value" do
CompaniesController.create.should_receive(:validates_fbid).with(company)
.and_return('companyid')
end
it "should fbid validation passed" do
CompaniesController.create.stub(:validates_fbid).and_return('companyid')
company.fbid.should_not be_nil
company.fbid.should == 'companyid'
company.save
expect { click_button submit }.to change(Company, :count).by(1)
end
end
回答by Henry
You don't want to stub the method, when it is the subject of your test case
当它是测试用例的主题时,您不想存根该方法
context "#validate_fbid" do
#test the function here
#don't stub
end
when you test the create action in the controller, you can stub "validate_fbid"
当您在控制器中测试创建操作时,您可以存根“validate_fbid”
describe "post create" do
...
CompaniesController.any_instance.stub(:validates_fbid).and_return('companyid')
...
end
Hope it helps.
希望能帮助到你。
回答by jurglic
When code is hard to test, it is usually because it is complex.
当代码难以测试时,通常是因为它很复杂。
You should refactor this code this way:
您应该以这种方式重构此代码:
- move the verification logic into new 'service class' which has a single responsibility of company verification on facebook
- this will make verification functionality independent of web layer and mucheasier to test
- make spec for service class which will test this code in isolation (no controllers)
- cleanup the controller of logic - you don't want to have logic inside your controllers (rule of thumb: one level of nesting max)
- spec for controller will be easier as well
- 将验证逻辑移到新的“服务类”中,它在 facebook 上有一个单一的公司验证责任
- 这将使验证功能独立于 web 层并且更容易测试
- 为服务类制定规范,它将单独测试此代码(无控制器)
- 清理逻辑控制器 - 您不想在控制器内部包含逻辑(经验法则:最大嵌套一级)
- 控制器的规范也会更容易
The controller code can look something like this:
控制器代码可能如下所示:
def create
company = Company.new(params[:company])
verified = FbCompanyVerifier.new.verify(company)
if verified and company.save
# success logic
else
# fail logic
end
end
回答by Andrew Feng
If you are testing controller, you can access controller directly:
如果您正在测试控制器,则可以直接访问控制器:
controller.stub(:message) { 'this is the value to return' }
回答by bigtex777
Here's the recommended syntax for Rspec 3 (3.3):
以下是 Rspec 3 (3.3) 的推荐语法:
allow_any_instance_of(CompaniesController).to receive(:validates_fbid).and_return("companyid")
allow_any_instance_of(CompaniesController).to receive(:validates_fbid).and_return("companyid")
or
或者
expect_any_instance_of(CompaniesController).to receive(:validates_fbid).and_return("companyid")
expect_any_instance_of(CompaniesController).to receive(:validates_fbid).and_return("companyid")
source: https://relishapp.com/rspec/rspec-mocks/docs/working-with-legacy-code/any-instance
来源:https: //relishapp.com/rspec/rspec-mocks/docs/working-with-legacy-code/any-instance

