jimweirich / rspec-given

Given/When/Then keywords for RSpec Specifications
https://github.com/jimweirich/rspec-given
MIT License
653 stars 61 forks source link

How to test message expectations? #20

Closed JeanMertz closed 11 years ago

JeanMertz commented 11 years ago

I was wondering how I should test message expectations using should_receive with rspec-given?

Here's an example I have:

    context 'persists correct signup data' do
      Given do
        subject.params = { signup: build(:signup).attributes }
        subject.signup.stub(:persist!)
      end

      When { subject.call }
      Then { subject.signup.should_receive(:save).and_return(true) }
    end

This fails for not receiving the message.

       (#<Signup:0x007fb4598206a8>).save(any args)
           expected: 1 time
           received: 0 times

I know the method is being called, because I used to check expect{ subject.call }.to change{ User.count }, but I'd like to rewrite the spec to never hit the database.

I wonder if it's because I am misusing rspec-given in this case? The reason I ask is that I call the method in the When clause, and after that set the expectation in the Then clause. This seems counter to I normally write it in RSpec (first an expectation, then the action).

cpuguy83 commented 11 years ago

I think you are not doing something right. It looks like you are testing that a stubbed method returns true... Which in this case you haven't told it to, and would be pointless to test this because you are trying to test a stubbed method.

I would say do not worry about testing persistence. If you merely test that the record is valid you can assume it will persist... "foo.should be_valid"

jimweirich commented 11 years ago

What mocking framework are you using? With most mock libraries, you have to setup the expectations before the When code is run (i.e. in a Given or before block).

If want to check expectations in a Then clause, then you need to use a mock framework that supports spies. Flexmock will support spies. I've heard that RSpec mocks also support them (or will soon? I don't have details).

See https://github.com/jimweirich/flexmock#spies for details on using spies with flexmock.

JeanMertz commented 11 years ago

It looks like you are testing that a stubbed method returns true

No, I haven't stubbed save, I've only stubbed persist! (so it doesn't touch the database). This is not a standard AR model, so that's why I want to test if save is called correctly.

However, I'm not quite sure if I can use should_receive on a non-stubbed method. I'm not even sure if I've written the correct expectation using the default rspec mocks.

Anyway, thank you for your responses, I will continue investigating why this fails.

jimweirich commented 11 years ago

Looks like spies will be in RSpec 2.14 (which isn't out yet). In the meantime, you can try out https://github.com/technicalpickles/rspec-spies