使用instance_double

时间:2017-10-11 14:51:29

标签: ruby-on-rails rspec

我是测试和学习Rspec的新手,而且我无法开始工作。

(我已经阅读了“使用Rspec3进行有效测试,以及许多教程......还有pluralsight.com”这本书)

情况很简单。在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,使用实例double ...来测试创建操作,并模拟&#34; save()&#34 ;回归真......等等。

我不知道我是否能很好地解释自己,但考虑到控制器的create动作,如何使用mocks和stub来测试,instance_double?

由于

2 个答案:

答案 0 :(得分: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代码时,我们才需要存根这些代码。因为对于所有这些,我们将分别编写规范。因此,无需再次测试我们为什么要进行存根。

答案 1 :(得分:0)

感谢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