2017-10-11 64 views
0

我是测试和学习Rspec的新手,我无法让它工作。使用instance_double与belongs_to关联的Rspec3控制器进行测试

(我已阅读与Rspec3书有效的测试,很多教程...也pluralsight.com)

的情况是非常简单的。在Companies控制器我想测试去创建方法,该company模型belongs_to user,这是代码:

我认为这个问题是测试执行

时:expect(Company).to receive(:new).with(company_params)

或控制器: @company.user=helpers.user

控制器:

class CompaniesController < SessionsController 

    def create 
    @company=Company.new(company_params)  
    @company.user=helpers.user 

    if @company.save() 
     redirect_to companies_path 
    else 
     render :edit 
    end 
    end 

和RSpec:

RSpec.describe CompaniesController, type: :controller do 

    let(:user) { instance_double(User) } 

    before do 
     allow_any_instance_of(ApplicationHelper).to receive(:user){user} 
     allow(controller).to receive(:authorize){true} 
    end 

    describe 'Authenticated user with companies' do 

     let(:company_params) { {company:{name:"Albert",domain:"www.albert.com"}} } 
     let(:company) { instance_double(Company) } 

     before do 
     allow(Company).to receive(:new){company} 
     end 

     describe 'POST #create' do 
     context "with valid data" do 

      before { allow(company).to receive(:save){true} } 

      it "redirects to companies_path" do 

      expect(Company).to receive(:new).with(company_params) 
      expect(company).to receive(:user=).with(user) 

      post :create, params:{company: company_params} 
      expect(response).to redirect_to(companies_path) 

      end 

我的目的很简单:使用instance_double嘲笑(或存根)@company和Company.new,使用实例双...测试创建行动,并模拟“保存()“返回true ...等

我不知道我是否很好地解释了自己,但是鉴于控制者的create行为,如何使用mocks ans stubs,instance_double进行测试?

感谢

回答

1

,首先让我来解释一下,我们需要在这里测试

def create 
    @company=Company.new(company_params)  
    @company.user=helpers.user 

    if @company.save() 
     redirect_to companies_path 
    else 
     render :edit 
    end 
    end 

我们正在测试控制器的create行动。首先让我们看看这个动作是做什么的?只需输入comapany_params作为输入,并在数据库中创建公司记录。

测试也是一样的,我们只需要传递需要的动作,需要检查它是否在数据库中创建记录。

RSpec.describe CompaniesController, type: :controller do 

    let(:user) { instance_double(User) } 

    before do 
    # all your authentication stubing goes here 
    allow_any_instance_of(ApplicationHelper).to receive(:user){user} 
    allow(controller).to receive(:authorize){true} 
    end 


    describe 'POST#create' do 
    context 'with valid attributes' do 
     before do 
     post :create, { company:{ name:"Albert", domain:"www.albert.com"} } 
     end 

     it 'responds with success' do 
     expect(response.status).to eq(302) 
     end 

     it 'creates company' do 
     company = Company.find_by(name: "Albert") 

     expect(assigns(:company)).to eq(company) 
     expect(response).to redirect_to(companies_path()) 
     end 
    end 

    context 'with invalid attributes' do 
     before do 
     post :create, { company:{ name:"", domain:""} } 
     end 

     it 'renders new template' do 
     expect(response).to render_template(:edit) 
     end 
    end 
    end 
end 

没有必要在这里分任何东西。据我所知,只有当我们使用任何lib classes/background jobs/third party libraries代码里面的行动,然后我们需要存根这些代码。因为对于所有这些,我们将分别编写规格。所以在这里不需要再次测试,这就是我们为什么要存根的原因。

+0

谢谢您回应,我会记住将来的测试。无论如何,在Pluralsight课程之后,我已经看到了如何在Create方法中存储所有方法,但不是Activerecord,只是简单的对象,而且我想知道如何存根,@ company.user =和xxx = Company.new(company_params)'...用'allow'和'expect' ...是否有可能将这些关联存根?我的代码应该如何在没有崩溃的情况下工作?再次感谢 –

0

感谢Narsimha Reddy,我对如何测试有更好的想法。 Eventhough,如果我想存根

@company=Company.new(company_params)  
@company.user=helpers.user 
if @company.save() 

仅用于测试德create的回应,该解决方案是一个很好用的参数,并允许allow(company).to receive(:user=)为belongs_to的关联

let(:company_params) {{company:{name:"Albert",domain:"www.albert.com"}}} 
    let(:ac_company_params) {ActionController::Parameters.new(company_params).require(:company).permit!} 

    let(:company) { instance_double(Company) } 

    before do 
    allow(Company).to receive(:new){company} 
    allow(company).to receive(:user=) 
    allow(company).to receive(:save){true} 
    end 

    it "redirects to companies_path" do 
    expect(Company).to receive(:new).with(ac_company_params) 
    expect(company).to receive(:user=).with(user) 

    post :create, params: company_params 
    expect(response).to redirect_to(companies_path) 
    end 
相关问题