rico_mac
rico_mac

Reputation: 888

what exactly is this rspec stub :where and what does it do?

I am looking through some tests written by other people and i keep seeing ':where' in their tests. I guess its a stub, but just finding my feet with testing and want to know is it any different from a normal stubs, what does the naming imply?

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

I can see what is going on here (I think), things like ':new' are controller actions right?

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

Upvotes: 0

Views: 421

Answers (2)

mykewould
mykewould

Reputation: 63

They are class or instance methods on the model. Lets just say that the model variable in your example is set to the Dog model and this is testing the 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

Now I want to test whats going on in my controller, but I don't want to test anything that my model actually does. I'm isolating a unit of my code to be tested. This is different than testing how it all works integrated together (google unit testing or integration testing).

In order to test just whats going on in my controller I stub the methods happening on my model to keep things isolated and clean. The way I do this is by stubbing it out in my controller spec. So In my DogControllerSpec I do:

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

So I'm saying allow my dog class to receive the 'where' method call, but don't execute its logic, and instead return me an empty array.

Then I can setup up the code I'm actually testing which is that my destroy method renders new when called.

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

The key here is really that you are attempting to decouple your tests, so that when you unit test your DogController#destroy you are not testing your Dog.where method. The reasoning being that if you change code in your Dog model it should not break specs in your DogControllerSpec.

Upvotes: 2

euwest
euwest

Reputation: 31

They are using symbol #to_proc, I believe, to 'stub' calling the method #where on model. So that means the line: allow(model).to receive(:where).and_return(no_instances) is essentially model.where #=> [].

:new is a controller action, but the way this code is using it is more like SomeClass.new, i.e. the method to create an instance of a class(which is the model).

Upvotes: 0

Related Questions