【问题标题】:Testing with Rspec3 controllers with belongs_to association using instance_double使用 instance_double 使用带有 belongs_to 关联的 Rspec3 控制器进行测试
【发布时间】:2017-10-16 23:32:12
【问题描述】:

我是测试和学习 Rspec 的新手,我无法让它正常工作。

(我已经阅读了《Effective testing with Rspec3》一书,以及许多教程...还有复数网站)

情况很简单。在Companies 控制器中,我想测试de Create 方法,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,使用 instance double...测试创建操作,并模拟“save()”返回 true...等等

我不知道我是否解释得很好,但是鉴于create 的controlloer 动作,如何使用模拟和存根进行测试,instance_double?

谢谢

【问题讨论】:

    标签: ruby-on-rails rspec


    【解决方案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 代码时,我们才需要存根这些代码。因为对于所有这些,我们将单独编写规范。所以这里不需要再次测试,这就是我们要做存根的原因。

    【讨论】:

    • 感谢您的回复,我会记住它以备将来测试。无论如何,在 Pluralsight 课程之后,我已经看到了如何在 Create 方法中存根所有方法,但它不是 Activerecord,只是简单的对象,我想知道如何存根,@company.user= 和 `xxx=Company.new (company_params)... with allow` 和expect...是否可以存根这个关联?我的代码应该如何工作而不会崩溃?再次感谢
    【解决方案2】:

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

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

    仅测试de 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-22
      • 2018-10-01
      • 1970-01-01
      • 2012-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多