如何模拟服务对象?我应该嘲笑它吗?

时间:2014-04-12 23:59:16

标签: ruby-on-rails ruby rspec mocking stubs

我有一个名为ResetPassword的服务对象,它处理ResetPassword Controller创建操作的所有逻辑。我也已经测试了服务对象。我应该模拟服务对象吗?我认为我应该准备好测试,它会减少运行规格。我目前为控制器的测试代码如下。不确定是否应该这样写。

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

1 个答案:

答案 0 :(得分:0)

我认为你应该在控制器中模拟服务,但是通过在类上注入模拟而不是存根来模拟它或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。这也将检查存根类实际上是否存在存根方法。这可以从RSpec 3.0.0.beta *

获得
let(:password_service) { instance_double(PasswordService, reset_password: nil) }