Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rspec:控制器中的存根方法_Ruby On Rails_Rspec_Ruby On Rails 3.2_Mocking_Stub - Fatal编程技术网

Ruby on rails Rspec:控制器中的存根方法

Ruby on rails Rspec:控制器中的存根方法,ruby-on-rails,rspec,ruby-on-rails-3.2,mocking,stub,Ruby On Rails,Rspec,Ruby On Rails 3.2,Mocking,Stub,我可以知道如何创建控制器创建方法中的存根方法吗?我需要为此编写规范,但我遇到了这些错误。我需要检查controller中的create方法,在模型中创建新的公司记录之前,必须执行validate_fbid方法 错误: 1) Companies new company create with valid information#validate_fbid should have correct parameters and return value Failure/Error: Companie

我可以知道如何创建控制器创建方法中的存根方法吗?我需要为此编写规范,但我遇到了这些错误。我需要检查controller中的create方法,在模型中创建新的公司记录之前,必须执行validate_fbid方法

错误:

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)>'
请求/公司\u 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    

当方法是测试用例的主题时,您不希望将其存根

context "#validate_fbid" do
  #test the function here
  #don't stub
end
在控制器中测试创建操作时,可以存根“validate_fbid”


希望能有所帮助。

当代码很难测试时,通常是因为代码很复杂

您应该以以下方式重构此代码:

  • 将验证逻辑转移到新的“服务类”中,该类在facebook上只负责公司验证
  • 这将使验证功能独立于web层,并且更易于测试
  • 为将单独测试此代码的服务类制定规范(无控制器)
  • 清理控制器的逻辑-您不希望控制器中有逻辑(经验法则:嵌套最大值的一个级别)
  • 控制器的规格也会更简单
控制器代码可以如下所示:

def create
  company = Company.new(params[:company])
  verified = FbCompanyVerifier.new.verify(company)

  if verified and company.save
    # success logic
  else
    # fail logic
  end
end

如果您正在测试控制器,则可以直接访问控制器:

controller.stub(:message) { 'this is the value to return' }

以下是Rspec 3(3.3)的推荐语法:

  • 允许(CompaniesController.)的任何实例接收(:验证fbid)并返回(“companyid”)

  • 期望(CompaniesController.)的任何实例接收(:验证fbid)并返回(“companyid”)

资料来源:

Hi,感谢您的回复。这是否意味着我需要创建一个具有“new”方法和“verify”方法的类FbCompanyVerifier?我想我不允许在控制器页面中创建类,所以我应该创建哪个文件夹“FbCompanyVerifier”?谢谢你的澄清。我对此非常陌生。正确-一个完整的类,实例方法为“verify”,如果“new”(initialize)方法没有任何作用,您可以跳过它。通常这是一种最佳实践,因此您可以使用一流对象/普通ruby对象。(有些可能将类与类方法一起使用,这有其自身的优点和缺点)。由于该类依赖于您的模型公司,因此您应该将其放在应用程序文件夹“app/services”中的某个位置。您可以将包含一两个方法的独立于web层的小型单责任类放在其中。您还可以查看code_climate博客文章,该文章描述了类似的重构—将逻辑代码提取到具有单责任的新类中,编写简单的规范,然后将其用作PORO(普通的旧ruby对象)在代码中…:如果
FbCompanyVerifier#verify
执行HTTP请求(或您希望在测试期间避免的任何其他副作用),您如何测试以防止它?在
FbCompanyVerifier
上使用
allow\u any\u instance\u of
allow\u any\u instance\u of(CompaniesController)。接收(:validates\u fbid)。并返回rspec3的('companyid')
。这个答案对我有效,因为当我存根该方法时,我知道它需要一个参数,但我不知道参数是什么。我只想传递参数,所以我使用带有参数的块来重写(存根)方法。
def create
  company = Company.new(params[:company])
  verified = FbCompanyVerifier.new.verify(company)

  if verified and company.save
    # success logic
  else
    # fail logic
  end
end
controller.stub(:message) { 'this is the value to return' }