2

我有一个名为 ResetPassword 的服务对象,它处理 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

或者更好的是,使用 aninstance_double代替。这还将检查存根方法是否实际存在于存根类中。这可从 RSpec 3.0.0.beta* 获得

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

您可以使用 mockito 来模拟您的服务,并使用 mockito 模拟多个服务。

于 2021-12-08T18:58:46.423 回答