2

ResetPassword Controller 作成アクションのすべてのロジックを処理する ResetPassword というサービス オブジェクトがあります。また、サービス オブジェクトは既にテスト済みです。サービス オブジェクトをモックする必要がありますか? テスト済みであり、実行中の仕様が削減されるため、そうする必要があると思います。これまでのコントローラーのテスト コードは以下のとおりです。このように書くべきかどうかはわかりません。

require 'spec_helper'

describe ResetPasswordController do
  describe "POST create" do
    context "when email matches a user" do
      let(:user) { Fabricate(:user) }

      it "calls password_reset on PasswordReset" do
        ResetPassword.stub(:reset_password)
        ResetPassword.any_instance.should_receive(:reset_password)
        post :create, email: user.email

      end
      it "redirects to root path" do
        post :create, email: user.email
        expect(response).to redirect_to root_path
      end
    end
    context "when email doesn't match a user" do
      it "redirects to new"
      it "displays a flash error"
    end
  end
end
4

2 に答える 2

1

コントローラーでサービスをモックする必要があると思いますが、クラスにスタブする代わりにモックを注入してモックするか、any_instance

コントローラーは次のようになります

class ResetPasswordController < ApplicationController
  def create
    reset_password_service.reset_password(params[:email])
  end

  def reset_password_service
    @reset_password_service ||= ResetPassword.new
  end

  def reset_password_service=(val)
    @reset_password_service = val
  end
end

次に、仕様で次のことができます

before { controller.reset_password_service = password_service }
let(:password_service) { double("PasswordService", reset_password: nil) }

it "does something good" do
  post :create, email: "foo"
  expect(password_service).to have_received(:reset_password).with("foo")
end

または、instance_double代わりに a を使用することをお勧めします。また、スタブ化されたメソッドがスタブ化されたクラスに実際に存在することも確認します。これは RSpec 3.0.0.beta* から利用可能です

let(:password_service) { instance_double(PasswordService, reset_password: nil) }
于 2014-04-14T09:30:43.233 に答える