0
votes

Trying to build a controller spec using rspec on a rails controller I have named "API::ZipsController".

The controller accepts a parameter called "zip_code" and returns an active record model and 200 status.

However, when I run rspec the test fails with NoMethodError: undefined method 'where' for Zip:Module. I believe this is because 'where' is an instance method, not a class method so I will need to stub/mock it? Unfortunately I have not had any luck in resolving the problem as of yet.

zips_controller_spec.rb:

describe API::ZipsController do
require 'spec_helper'
it "returns 200 status with zones data" do
        get 'show', zip_code: "V9A1B2"
        response.should be_success
  end
end

api/zips_controller.rb - (working):

class API::ZipsController < ApplicationController
  def show
    zip = Zip.where(zip_code: params[:zip_code].upcase.slice(0..2))
    render json: zip, status: 200
  end
end

zip.rb (model):

class Zip < ActiveRecord::Base
def as_json(options)
super(:only => [:zip_code])
end
end
2
aren't you missing a require in your spec? - moeabdol
@moeabdol yes, edited my code post above to include 'spec_helper'. It was in my code all along though. - Jon Girard
Can you show Zip class? - ihaztehcodez
actually where is a class method! Can you show Zip class? - moeabdol
@moeabdol added the zip class to the post above.. it's just used to super the as_json definition. I tried to use "find" instead of where but get the error 'ActiveRecord::RecordNotFound (Couldn't find Zip with 'id'={:zip_code=>"V9A"})' because it tries to find it by id, where I need to find by the zip_code column which 'where' seemed to work for - Jon Girard

2 Answers

2
votes

You have a Zip module defined somewhere that is conflicting with your Zip model. It could be somewhere in your code or something trickier like the use of the rubyzip gem.

You could namespace the model in another module as suggested in another answer or rename the model to something else like Zipcode.

1
votes

Do it this way:

  require 'spec_helper'

  describe API::ZipsController, type: :controller do
    let(:zip_code) { "V9A1B2" }
    let(:params) { { zip_code: zip_code } }
    let(:zip) { double('zip') }

    before do
      allow(Api::Zip).to receive(:where).with(zip_code) { zip }
    end

    it "returns 200 status with zones data" do
      get 'show', params
      response.should be_success
    end
  end

Update

Try to put your Zip class under a module, say Api and put it under app/models/api/zip.rb file:

module Api
  class Zip < ActiveRecord::Base
    def as_json(options)
      super(:only => [:zip_code])
    end
  end
end

And, then try the above code.