Denise Mauldin
Denise Mauldin

Reputation: 5615

rails rspec mock_model Object expected, got String

I have a Directory controller and a Files controller. I'm testing the Files controller. I've created valid attributes for the File and I'm trying to mock_model the Directory to get the test to pass. The GET tests all work, but none of the POST tests work. The POST tests all give the error: "Directory expected, got String."

describe FilesController do
   def valid_attributes {
       :name => "test",
       :reference_id => 1,
       :location => "/path/to/directory",
       :software => "excel",
       :software_version => "2010",
       :directory => mock_model(Directory)
    }
   end

 describe "POST create" do
   describe "with valid params" do
     it "creates a new AssemblyFile" do
       expect {
         post :create, :assembly_file => valid_attributes
       }.to change(AssemblyFile, :count).by(1)
     end

     it "assigns a newly created assembly_file as @assembly_file" do
       post :create, :assembly_file => valid_attributes
       assigns(:assembly_file).should be_a(AssemblyFile)
       assigns(:assembly_file).should be_persisted
     end

     it "redirects to the created assembly_file" do
       post :create, :assembly_file => valid_attributes
       response.should redirect_to(AssemblyFile.last)
     end
   end
end

1) FilesController POST create with valid params creates a new File
 Failure/Error: post :create, :file => valid_attributes
 ActiveRecord::AssociationTypeMismatch:
   Directory(#87017560) expected, got String(#49965220)
 # ./app/controllers/files_controller.rb:60:in `new'
 # ./app/controllers/files_controller.rb:60:in `create'
 # ./spec/controllers/files_controller_spec.rb:79:in `block (5 levels) in <top (required)>'
 # ./spec/controllers/files_controller_spec.rb:78:in `block (4 levels) in <top (required)>'

If I look at the test.log file, it shows that assembly is a string ("assembly" => "1011"). So I'm not sure why the mock_model isn't creating an object?

I've tried using stub! instead of mock_model, but that gets complicated because the create! used for stub! needs a lot of its own valid variables set and I don't really want to have to set a whole bunch of other valid attributes for that when I'm not trying to even test the Directory controller at all.

What am I doing wrong in my approach here?

Upvotes: 0

Views: 1317

Answers (1)

zetetic
zetetic

Reputation: 47548

Pass the id of the mock in the params hash instead of the mock itself. You'll also need to stub the find method so the mock is available in the controller action:

@directory = mock_model(Directory)
Directory.stub(:find).with(@directory.id).and_return(@directory)
post :create, :assembly_file => valid_attributes.merge(:directory_id => @directory.id)

# in controller
@directory = Directory.find(params[:assembly_file][:directory_id]) # => returns the mock

Upvotes: 1

Related Questions