-1

我是 Rails 的新手,我现在正在尝试使用 stubbs 和 mocks 测试我的控制器代码。我尝试在代码上使用模拟,但我不能正确地做到这一点。请帮助我解决重构的正确代码。请帮助我解释您编写的代码。

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

4

2 回答 2

2

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

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

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 文档是这也是一个不错的地方。

于 2016-04-06T17:38:06.817 回答
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 }参数hash的方法,最后一个会失败。希望有帮助。

于 2016-04-05T06:21:50.750 回答