Op 19-mrt-08, om 16:33 heeft Dave het volgende geschreven:

> Hi there,
>
> I'm still trying to wrap my head around when to use a stub and a mock.
> If I understand this right, I should be using a 'mock' when imitating
> an object, but not its behavior. I should be using a stub when I want
> to imitate the behavior of an object. Does that sound about right?
>
> With that said, I'm struggling a little trying to spec out this
> instance method that is available to a User object. The method takes
> an OrderPaymentInfo object and copies its attributes onto the User's
> attributes (Ignore the clunky design... that's just how it has to be).
>
> The User's instance method looks like so:
>
> class User
>       def update_billing_info(billing_info)
>         unless self.has_billing_address?
>           self.bill_to_address1             = billing_info.address1
>           self.bill_to_address2             = billing_info.address2
>           self.bill_to_address3             = billing_info.address3
>           self.bill_to_city                 = billing_info.city
>           self.bill_to_country_code         = billing_info.country_code
>           self.bill_to_state_province_code  =  
> billing_info.state_province_code
>           self.bill_to_postal_code          = billing_info.postal_code
>           self.bill_to_phone_number         = billing_info.phone_number
>           self.bill_to_extension            = billing_info.extension
>           self.bill_to_fax                  = billing_info.fax_number
>           self.save ? true : false
>         else
>           true
>         end
> end
>

If this is activerecord you could use  
self.update_attributes(billing_info)

>
> Here's the spec:
>
> describe User, "when checking billing information" do
>  before(:each) do
>    @user = User.new(:id => 1)
>    @order_payment_info = mock_model(OrderPaymentInfo,
>                                    :id => 1,
>                                    :user_id => @user.id,
>                                    :address1 => "555 Rd.",
>                                    :address2 => "Ste 2",
>                                    :address3 => "line 3",
>                                    :city => "Chicago",
>                                    :country_code => "USA",
>                                    :state_province_code => "IL",
>                                    :psotal_code => "12345",
>                                    :phone_number => "5551234321",
>                                    :extension => "123",
>                                    :fax_number => "5551234321")
>    @user.stub!(:update_billing_info).with(@order_payment_info)
>  end

You just stubbed update_billing_info (called with @order_payment_info)  
on @user, which means the real method will not be used anymore. Your  
tests will use the stub instead of the real method. Don't stub the  
very thing you want to test!

>
>
>  it "should update billing information when User's billing info is  
> nil" do
>     
> @user.should_receive(:update_billing_info).with(@order_payment_info)
>    @user.update_billing_info(@order_payment_info)
>    @user.stub!(:has_billing_address?).and_return(false)
>    @user.bill_to_address1.should eql("555 Rd.")
>    @user.bill_to_address2.should eql("Ste 2")
>  end
>
>
> end
>
> When I run this spec I get an "error" of:
>
> 1)
> 'User when checking billing information should update billing
> information when User's billing info is nil' FAILED
> expected "555 Rd.", got nil (using .eql?)
>

Try to test one thing at a time, you shouldn't test everything about  
that method in one test. To me your test description does not tell a  
thing:

'User when checking billing information should update billing  
information when User's billing info is nil'

This says much more:

'User instance object update_billing_info should update the billing  
address part 1'

You can build this up like this:

describe User, "instance object" do
        before(:each) do
                @user = User.create( ... )
        end
        describe "update_billing_info" do
                it "should update the billing address part 1" do
                        @user.update_billing_info( @order_payment_info )
                        @user.bill_to_address1.should == "555 Rd."
                end
                it "should ..." ...
        end
end


Try to make small tests (make a new test if the first works) and try  
to build the model with the tests instead of the other way around.

gr
Ivo
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to