这个rspec存根究竟是什么:它在哪里以及它做了什么?

时间:2014-07-14 00:32:56

标签: ruby-on-rails rspec

我正在查看其他人编写的一些测试,并且我会在测试中看到':where'。我猜它是一个存根,但只是通过测试找到我的脚并想知道它与普通的存根有什么不同,命名意味着什么?

describe "delete destroy" do
    context "is not allowed by user" do
      before do
        allow(model).to receive(:where).and_return(no_instances)
        allow(no_instances).to receive(:first).and_return(no_instances)
      end
      context "where the record is destroyed" do
        before do
          allow(instance).to receive(:destroy).and_return(true)
          delete :destroy, params_id
        end
        sets_flash(:notice)
        redirects_to('/airbrake_accounts')
      end
      context "where the record is not destroyed" do
        before do
          allow(instance).to receive(:destroy).and_return(false)
          delete :destroy, params_id
        end
        sets_flash(:error)
        redirects_to('/airbrake_accounts')
      end
    end
    context "where the record is not found" do
      before do
        allow(model).to receive(:where).and_return(no_instances)
        delete :destroy, params_id
      end
      sets_flash(:error)
      redirects_to('/airbrake_accounts')
    end
  end

我可以看到这里发生的事情(我认为),例如':new'控制者行动对吗?

describe "photo create" do
    before do
      allow(model).to receive(:new).and_return(instance)
    end
    context "where all is not well" do
      before do
        allow(instance).to receive(:save).and_return(false)
        post :create, params_new_instance
      end
      sets_flash(:error)
      it "should render the new form" do
        expect(response).to render_template("entries/new")
      end
    end
    context "where all is well" do
      before do
        allow(instance).to receive(:save).and_return(true)
        post :create, params_new_photo
      end
      sets_flash(:notice)
      redirects_to ('/photos')
    end
  end

2 个答案:

答案 0 :(得分:1)

它们是模型上的类或实例方法。让我们说你的例子中的模型变量设置为Dog模型,这是测试DogController。

# model
class Dog 
  def where(params) 
    do_stuff 
  end
 end

# controller
class DogController > ApplicationController
  def destroy
   @dogs = Dog.where(id: 1)
   redirect :new
  end
end

现在我想测试我的控制器中发生了什么,但我想要测试我的模型实际上做的任何事情。我正在隔离我要测试的代码单元。这与测试它们如何集成在一起(谷歌单元测试或集成测试)不同。

为了测试我的控制器中发生了什么,我将发生在我的模型上的方法存根,以保持隔离和清洁。我这样做的方法是在我的控制器规范中将其删除。所以在我的DogControllerSpec中我做:

before do 
  allow(Dog).to receive(:where).and_return([])
end

所以我说允许我的dog类接收'where'方法调用,但不执行它的逻辑,而是返回一个空数组。

然后我可以设置我实际测试的代码,这是我的destroy方法在调用时呈现新的。

it "should render the new form" do 
  expect(response).to render_template("dogs/new") 
end

这里的关键是你试图解耦测试,所以当你对DogController#destroy进行单元测试时,你没有测试你的Dog.where方法。原因在于,如果你在Dog模型中更改代码,它不应该破坏DogControllerSpec中的规范。

答案 1 :(得分:0)

我相信他们正在使用#to_proc符号来“stub”调用模型上的方法#where。这意味着这条线: allow(model).to receive(:where).and_return(no_instances) 本质上是 model.where #=> []

:new是一个控制器动作,但是这个代码使用它的方式更像是SomeClass.new,即创建类实例的方法(它是模型)。