使用mock和stubb重构代码

时间:2016-04-05 06:10:59

标签: ruby-on-rails ruby unit-testing rspec rspec-mocks

我是rails的新手,我现在正试图使用​​stubbs和mock来测试我的控制器代码。我尝试在代码上使用mock但我无法正确执行。请帮我解决重构的正确代码。请帮我解释你写的代码。

require 'rails_helper'

RSpec.describe ArticlesController, type: :controller do
  let(:article) { create :article}
  let(:art_params) { attributes_for(:article) }
  let(:dbl) {double(:articles)}
  describe 'GET index' do
    it 'assigns @articles' do
      get :index
      allow(dbl).to receive(:articles).and_return article
      expect(dbl.articles).to eql(article)
      #expect_any_instance_of(Article).to receive(:save).and_return(true)
    end

    it 'renders the index template' do
      get :index
      allow(dbl).to receive(:articles)
      expect(response).to render_template('index')
    end
  end

  describe 'GET :new' do
    it 'render new template' do
      get :new
      expect(response).to render_template(:new)
    end
  end

  describe 'POST/create' do
    it 'created a new article ' do
    expect { post :create, article: art_params }.to change(Article, :count).by(1)
    end
  end

  describe 'POST/create not' do
    it 'did not create a new user' do
     # expect(art_params).to receive(attributes_for :article).with(content:)
      art_params = { article: attributes_for(:article, content: nil) }
      post :create, art_params
      expect(response).to render_template(:new)
    end
  end

  describe 'GET/edit' do
    it 'displays the edit template' do
      get :edit, id: article.id
      expect(response).to render_template(:edit)
    end
  end

  describe 'POST/update' do
    it 'displays the update template' do
      post :update, id: article.id, article: attributes_for(:article)
      expect(response).to redirect_to(article_path(article.id))
    end
  end

  describe 'POST/DELETE' do
    it 'destroys the article template' do
      dbl = double()
      article = create :article
      expect { delete :destroy, id: article.id }.to change(Article, :count).by(-1)

    end
  end
en

d

2 个答案:

答案 0 :(得分:2)

模拟和存根是相当先进的测试概念,以使其真正正确。如果没有真正的理解,很容易创建脆弱的测试,每次测试代码更改时都会中断。或者总是会通过的测试。

例如,以下代码不会失败。您创建一个测试double(dbl),然后在该double上存根方法(#articles)并指定此方法调用将返回实例article。期望你在test double上调用#articles方法,因为你刚刚在test double上定义了这个行为。

let(:article) { create :article }
let(:dbl) { double(:articles) } # the test double

it 'assigns @articles' do
  get :index
  allow(dbl).to receive(:articles).and_return article # stubbing
  expect(dbl.articles).to eql(article) # invoking the stubbed method
end

您可以尝试从该示例中删除get :index行,您将看到代码仍在传递。

您也可以在没有存根的情况下编写示例:

let(:article) { create :article }

it 'assigns @articles' do
  get :index
  expect(assigns(:articles)).to contain_exactly(article)
end

如果您开始使用Rails和RSpec进行编程,我建议您尽可能使用真实对象。 rspec-rails的文档有很多很好的例子:http://www.relishapp.com/rspec/rspec-rails/v/3-4/docs 如果你想了解更多关于模拟和存根的信息,那么RSpec文档也是一个非常好的地方。

答案 1 :(得分:1)

  # This is a stub
  fake_article = allow(article).to receive(:compute_price).and_return(200)

  # This too
  another_fake_article = double(compute_price: 200)

  # This is a mock
  expect(article).to receive(:where).with(status: :closed)

如果您的文章没有使用where参数哈希调用{ status: :closed }方法,则最后一个将失败。希望有所帮助。

相关问题