about searcing engines

Do you know? You can earn money from searcing engines… check this web site… there is also english language support…

www.search-earn.com/lamiacaner0505

Hi all,

I’m trying to understand rspec.

questions:-

  1. Can/should I use mock in model tests. I’m thinking to mock out models external to the test ie parent/child objects etc

  2. so assuming answer to question 1 is yes/yes how do i implement it. i tried…

company = mock_model(Company)

@listing = company.listing.create

running the test get this error

Spec::Mocks::MockExpectationError in ‘Listing should be valid’

Mock ‘Company_1000’ received unexpected message :listing with (no args)

so i should be using the

my_mock.should_receive(:listing).with(:no_args)

or so i thought i then got

NoMethodError in ‘Listing should be valid’

You have a nil object when you didn’t expect it!

The error occurred while evaluating nil.create

so maybe it’s not possible to do this? or maybe i need to pass somthing back? but what? i don’t really want to pass back a mock listing i want to test that it is created in the database properly

any pointers appreciated

nathan

Hi all,

I'm trying to understand rspec.

questions:-

1) Can/should I use mock in model tests. I'm thinking to mock out models external to the test ie parent/child objects etc

2) so assuming answer to question 1 is yes/yes how do i implement it. i tried..

company = mock_model(Company) @listing = company.listing.create

running the test get this error

Spec::Mocks::MockExpectationError in 'Listing should be valid' Mock 'Company_1000' received unexpected message :listing with (no args)

so i should be using the

my_mock.should_receive(:listing).with(:no_args)

or so i thought i then got

NoMethodError in 'Listing should be valid' You have a nil object when you didn't expect it! The error occurred while evaluating nil.create

so maybe it's not possible to do this? or maybe i need to pass somthing back? but what? i don't really want to pass back a mock listing i want to test that it is created in the database properly

This is not really an rspec question - it's a more general "mocking AR" question.

When you do this:

  company = mock_model(Company)

you're creating a mock object, not an instance of Company. The mock_model method adds some things to the mock object that are standard across AR objects, but it is still a mock object. Since :listing does not belong to AR::Base, you have to set up a stub or a message expectation for it - as you tried to do.

There is a meme, axiom, whatever, in TDD that says "test YOUR code, not other people's." What you're doing here is testing other people's code and you don't really need to do that. We all know that model.association.create works, and to test it you have to go through crazy mocking shenanigans like this:

listings = mock("listings") listing = mock_model(Listing) company.should_receive(:listings).and_return(listings) listings.should_receive(:create).and_return(listing)

Oy vey!

This is a case where I, for one, either allow DB access or use a tool like model_stubbing. I haven't tried NullDB yet but seems pretty cool too.

I do mock the hell out of AR from controller, view and helper specs. None of those ever go near a DB. But model specs are a gray area - no one right answer for all cases IMO.

HTH, David

Hi David,

Cheers for that I think I understand better how to mock. It makes
sense not to test active record but my motivations were different I
was trying to set-up records to test the validation rules I had created.

is something like the following considered code to test?

validates_presence_of :title, :if => published? validates_existence_of :company validates_existence_of :location, :if => published?

def published?    state == "published" end

and if so is it possible/advisable mock the company/location but not
the listing? I think your suggesting it isn't possible to do this
but... maybe I can mock Company and Location and create Listing as so

@company = mock_model(Company) @location - mock_model(Listing) company.should_receive(:id).and_return(1) listings.should_receive(:id).and_return(1) @listing = Lisitng.new(:company_id => @company.id, :location_id =>
@location.id

Are there any multi model examples of applications out there with
Rspec tests that I could study or Books maybe? I think this would
help me greatly understand what to test and what not to and how tests
are de coupled correctly. I'd love to see one made with stories
too, I've been writing stories but haven't tried to implemented them
yet, figured it would make sense to understand model tests and then
work my way up.. stories fascinate me because they get me thinking
about how it will look and feel to the user not just the behaviour.
Maybe I should be doing things top down from stories but I feel that
is a bit advanced for now :slight_smile:

cheers again for your input.. Nathan

Hi David,

Cheers for that I think I understand better how to mock. It makes sense not to test active record but my motivations were different I was trying to set-up records to test the validation rules I had created.

is something like the following considered code to test?

validates_presence_of :title, :if => published? validates_existence_of :company validates_existence_of :location, :if => published?

def published?    state == "published" end

and if so is it possible/advisable mock the company/location but not the listing? I think your suggesting it isn't possible to do this but... maybe I can mock Company and Location and create Listing as so

@company = mock_model(Company) @location - mock_model(Listing) company.should_receive(:id).and_return(1) listings.should_receive(:id).and_return(1) @listing = Lisitng.new(:company_id => @company.id, :location_id => @location.id

You don't really need mocks at all for describing the validation behaviour. Just create a listing, get it into the state you want and expect it to be valid or invalid as appropriate:

describe "a published Listing" do   def valid_attributes     {:title => "A Great Read",      :company => Company.new,      :listing => Listing.new}   end

  before(:each) do     @listing = Listing.new(valid_attributes)     @listing.stub!(:published?).and_return(true)   end

  it "should be valid with valid attributes" do     @listing.should be_valid   end

  it "should be invalid without a title" do     @listing.title = nil     @listing.should_not be_valid   end

  .... etc end

You could also write a custom matcher that lets you do stuff like this:

@listing.should_not be_valid_with(valid_attributes).less(:title)

Come to think of it, maybe we should just add that to rspec_on_rails! (Lighthouse - Beautifully Simple Issue Tracking)

Cheers, David

Are there any multi model examples of applications out there with Rspec tests that I could study or Books maybe?

I am working on an RSpec book that will have some material on Rails. This issue will definitely be addressed, but as I said before - there's no one right answer, so don't expect silver bullet solutions.

In the mean time, there are a few good books on TDD, which is part of the basis for BDD. In fact, if you read them you'll see things like "this is not a book about testing" and "focus on behaviour." Here are a couple of recommendations:

Test-Driven Development by Example (Kent Beck) Test-Driven Development, a Practical Guide (Dave Astels)

The won't teach you about Rails directly, but they do address decoupling and finding a related balance.

I think this would help me greatly understand what to test and what not to and how tests are de coupled correctly. I'd love to see one made with stories too,

There will be material in my book on Stories. Early in the book there is a worked example, developing a small command line application using stories together with object specs.

I've been writing stories but haven't tried to implemented them yet, figured it would make sense to understand model tests and then work my way up.. stories fascinate me because they get me thinking about how it will look and feel to the user not just the behaviour. Maybe I should be doing things top down from stories but I feel that is a bit advanced for now :slight_smile:

That's the trick. Often things that produce a simple and clear result have to do some complex things under the hood. This is true of all of the components in Rails, and certainly true of RSpec stories as well.

cheers again for your input..

My pleasure.

Cheers, David

cool I hadn't thought of doing a Company.new like that but makes
total sense... and i like

@listing.should_not be_valid_with(valid_attributes).less(:title)

it reads very nicely :slight_smile:

unfortunately i still doesn't work, so no fooling
validates_existence_of plugin that way

'a published Listing should be valid with valid attributes' FAILED Listing expected to be valid but had errors:    Company does not exist

also

'a published Listing should be invalid without a title' FAILED Matcher does not support should_not. See Spec::Matchers for more information about matchers.

am i missing a matcher or should i be writing one?

cheers Nathan

cool I hadn't thought of doing a Company.new like that but makes total sense... and i like

@listing.should_not be_valid_with(valid_attributes).less(:title)

it reads very nicely :slight_smile:

unfortunately i still doesn't work, so no fooling validates_existence_of plugin that way

I'm not sure what plugin you mean, but I don't maintain it. I'd recommend checking with its authors about whether they had mocking/stubbing in mind.

Cheers, David

OK cheers David I’ll do that

thanks for all your help :slight_smile:

Mocks Aren't Stubs is a great read. Decide yourself if you should be mocking at all or not.

I confess i had stumbled across that article previously but passed it over, cos it was too wordy :wink:

just read it though and it’s great i understand so much more now I hadn’t even been aware of a classic/mockist distinction. One interesting aspect is that as a beginner to testing i was in the mindset that i had to get all my tests for the model right before i could work my way out to the controller’s and views. now i realise you can work in to out or out to in per feature not per model. Also It hadn’t even occurred to me that you could develop your ui before ever developing the models below it, i guess stories will be great for this. i don’t think i would want to do that but it’s interesting to note that it can be done by using mocks.

one question which maybe you can help clarify for me. there is a line in the article

“It’s at this point that I should stress that whichever style of test you use, you must combine it with coarser grained acceptance tests that operate across the system as a whole. I’ve often come across projects which were late in using acceptance tests and regretted it.”

whats an acceptance test, is it an integration test by another name?

cheers

nathan

I know yr hoping to use that article as a bully pulpit but I just wanted to point out one phrase:

“So if mockist testing sounds appealing to you, I’d suggest giving it a try.”

Nowhere in the article does Fowler say “mocking is bad” as you imply with yr “[d]ecide yourself if you should be mocking at all or not.” :wink: Just had to clear that up.

RSL