title: mocking controller methods in rspec
body: <p>(This question is similar to <a href="https://stackoverflow.com/q/16628739/558639">Ruby on Rails Method Mocks in the Controller</a>, but that was using the old <code>stub</code> syntax, and besides, that didn't receive a working answer.)</p>
  
  <h2>short form</h2>
  
  <p>I want to test my controller code separate from my model code.  Shouldn't the rspec code:</p>
  
  <pre><code>expect(real_time_device).to receive(:sync_readings)
  </code></pre>
  
  <p>verify that <code>RealTimeDevice#sync_readings</code> gets called, but inhibit the actual call?</p>
  
  <h2>details</h2>
  
  <p>My controller has a #refresh method that calls <code>RealTimeDevice#sync_readings</code>:</p>
  
  <pre><code># app/controllers/real_time_devices_controller.rb
  class RealTimeDevicesController &lt; ApplicationController
    before_action :set_real_time_device, only: [:show, :refresh]
    &lt;snip&gt;
    def refresh
      @real_time_device.sync_readings
      redirect_to :back
    end
    &lt;snip&gt;
  end
  </code></pre>
  
  <p>In my controller tests, I want to verify that (a) that @real_time_device is being set up and (b) the #sync_reading model method is getting called (but I don't want to invoke the model method itself since that's covered by the model unit tests).  </p>
  
  <p>Here's my controller_spec code that doesn't work:</p>
  
  <pre><code># file: spec/controllers/real_time_devices_controller_spec.rb
  require 'rails_helper'
    &lt;snip&gt;
  
      describe "PUT refresh" do
        it "assigns the requested real_time_device as @real_time_device" do
          real_time_device = RealTimeDevice.create! valid_attributes
          expect(real_time_device).to receive(:sync_readings)
          put :refresh, {:id =&gt; real_time_device.to_param}, valid_session
          expect(assigns(:real_time_device)).to eq(real_time_device)
        end
      end
  
    &lt;snip&gt;
  </code></pre>
  
  <p>When I run the test, the actual <code>RealTimeDevice#sync_readings</code> method is getting called, i.e., it's trying to call code in my model.  I thought the line:</p>
  
  <pre><code>        expect(real_time_device).to receive(:sync_readings)
  </code></pre>
  
  <p>was necessary and sufficient to stub the method and verify that it got called.  My suspicion is that it needs to be a double.  But I can't see how to write the test using a double either.</p>
  
  <p>What am I missing?</p>