Forum: RSpec stub().and_raise() ain't raising?

Posted by Fearless Fool (fearless_fool)
on 2012-01-13 01:32
I have two blocks of tests: one for testing positive outcomes and one
for testing negative.  After poking around, I've concluded that the
underlying :verify_credentials method is getting called, despite the
stub:

  describe 'electricity credentials' do
    before(:each) do
      @wizard.electricity_service = MeteredService::Base.create!()
    end

      it 'with valid credentials should spawn external loader' do
        @wizard.electricity_service.stub(:verify_credentials).and_return(true)
        @wizard.electricity_loader.stub(:start)
        @wizard.electricity_loader.should_receive(:start)
        @wizard.validate_setting_electricity_credentials
      end

      it 'with invalid credentials should not spawn external loader' do
        @wizard.electricity_service.stub(:verify_credentials).and_raise('no
can do')
        @wizard.electricity_loader.stub(:start)
        @wizard.electricity_loader.should_not_receive(:start)
        @wizard.validate_setting_electricity_credentials
      end

    end

Am I missing something fundamental about .stub()?

- ff
Posted by Justin Ko (Guest)
on 2012-01-13 03:36
(Received via mailing list)
On Jan 12, 2012, at 5:32 PM, Fearless Fool wrote:

>      it 'with valid credentials should spawn external loader' do
>        @wizard.electricity_loader.should_not_receive(:start)
> Posted via http://www.ruby-forum.com/.
> _______________________________________________
> rspec-users mailing list
> rspec-users@rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users

What are the failed expectations? Just paste it.

Are you sure that @wizard.electricity_service is returning the same 
object on each call? If a database call is being made, there's a good 
chance it is returning a different object (which has not mocks).
Posted by Fearless Fool (fearless_fool)
on 2012-01-13 06:18
Justin Ko wrote in post #1040632:
> What are the failed expectations? Just paste it.

You've identified the problem (see below), but to answer your question:

  1) Wizard electricity credentials with valid credentials should spawn 
external loader
     Failure/Error: @wizard.electricity_loader.should_receive(:start)
       (#<Wizard::ElectricityLoader:0x000001029bc140>).start(any args)
           expected: 1 time
           received: 0 times
     # ./spec/models/wizard_spec.rb:181:in `block (4 levels) in <top 
(required)>'

> Are you sure that @wizard.electricity_service is returning the same
> object on each call? If a database call is being made, there's a good
> chance it is returning a different object (which has not mocks).

Ah!  I think that's the culprit -- @wizard.electricity_service invokes a 
db call:

class Wizard < ActiveRecord::Base
  def electricity_service
    premise.metered_services.where(:natural_resource_id => 
NaturalResource::ELECTRICITY.id)
  end
end

It seems obvious now that you point it out.  So in rspec-land, what's 
the stylistically appropriate way to test this?  Stub .any_class()?
Posted by Andrew Premdas (Guest)
on 2012-01-13 09:07
(Received via mailing list)
On 13 January 2012 05:18, Fearless Fool <lists@ruby-forum.com> wrote:
>      received: 0 times
> class Wizard < ActiveRecord::Base
> def electricity_service
>  premise.metered_services.where(:natural_resource_id =>
> NaturalResource::ELECTRICITY.id)
> end
> end
>

I think your tests are telling you to refactor your code. the
`premise.metered_services.where` is breaking the law of demeter. This
makes it hard to stub/mock. I'd also question the naming of the Wizard
class. One thing to consider doing is running the tests with the
pretty output and reading it.

So why should Wizard#electricity_service spawn an external loader? Why
should a Wizard have an electricity service etc.

There ia a tendency when writing specs, to focus on getting the spec
to pass, and doing complicated things to make this happen. But really
its much more important to listen to the tests to make things clear
and simple.

In this case perhaps there is an ElectricityService class asking to be 
born.

HTH

Andrew

> It seems obvious now that you point it out. So in rspec-land, what's
> the stylistically appropriate way to test this? Stub .any_class()?
>
> --
> Posted via http://www.ruby-forum.com/.
> _______________________________________________
> rspec-users mailing list
> rspec-users@rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users



--
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.