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