On Wed, Feb 3, 2010 at 2:07 PM, <m...@franklakatos.com> wrote: > I absolutely love the idea of encapsulated the daisy chained calls > (c_u.comp.project) into a controller methods so all i gotta do is stub that > out.
Oooh, I hate that one :) You're adding lots of small methods that actually don't define how the class should behave, IMO. In fact, how a client or project is related to a user is a responsibility of the models, not the controllers. I would much rather turn @client = current_user.company.clients.find(params[:project][:client_id]) @project = @client.projects.build(params[:project]) into @client = current_user.find_client(params[:project][:client_id]) @project = @client.projects.new(params[:project]) And add the helper method on the models. Even more: @project = current_user.add_project(params[:project]) And let the handling of the client and the business rules ("a project must belong to a client") to the models, as well Then your controller would be a lot slimmer, and the tests for it much simpler. def create @project = current_user.add_project(params[:project]) if @project.save flash[:notice] = "Added '#...@project.name}'" redirect_to somewhere else render :new end end Cheers, -foca > > Once again, thanks++ > Frank > > > Quoting David Chelimsky <dchelim...@gmail.com>: > >> On Wed, Feb 3, 2010 at 8:52 AM, <m...@franklakatos.com> wrote: >>> >>> Ok, so these ideas seem kind of natural to me, which is nice: >>> >>> mock_models being used to mock non-tested models >>> stub for queries and/or well-tested methods, should_receives for commands >>> >>> While reading over Dave Astlels, I kind of got concerned because of >>> something he states that I feel I'm doing in my specs: >>> >>> "When you realize that it's all about specifying behaviour and not >>> writing >>> tests, your point of view shifts. Suddenly the idea of having a Test >>> class >>> for each of your production classes is ridiculously limiting. And the >>> thought of testing each of your methods with its own test method (in a >>> 1-1 relationship) will be laughable." >>> >>> This is what I am striving for, but being guided simply by rSpec error >>> messages results me in writing specs like this... >>> >>> describe "POST 'create'" do >>> >>> before do >>> �...@current_user = mock_model(User) >>> controller.stub(:current_user).and_return @current_user >>> �...@company = mock_model(Company) >>> �...@current_user.should_receive(:company).and_return @company >>> �...@clients = mock("Client List") >>> �...@company.should_receive(:clients).and_return @clients >>> end >>> >>> describe "when client is found" do >>> >>> before do >>> �...@client = mock_model(Client) >>> �...@clients.should_receive(:find).and_return @client >>> end >>> >>> describe "on successful save" do >>> >>> before do >>> �...@projects = mock_model(ActiveRecord) >> >> This is a little odd. @projects is a collection, not a an instance, >> and mocking ActiveRecord explicitly seems a bit odd. I'd generally us >> a simple array: >> >> @projects = [] >> >>> �...@client.should_receive(:projects).and_return @projects >>> �...@project = mock_model(Project) >>> �...@projects.should_receive(:build).and_return @project >>> �...@client.should_receive(:save).and_return true >>> �...@project.should_receive(:name).and_return "New Project" >>> end >>> >>> it "should set up the flash" do >>> post "create", {:project => {:client_id => 1}} >>> flash[:notice].should_not be_nil >>> end >>> >>> end >>> >>> end >>> >>> >>> end >>> >>> >>> >>> ... for a controller that looks like this ... >>> >>> >>> def create >>> �...@client = >>> current_user.company.clients.find(params[:project][:client_id]) >>> �...@project = @client.projects.build(params[:project]) >>> if @client.save >>> flash[:notice] = "Added: #...@project.name}" >>> else >>> render :new >>> end >>> end >>> >>> >>> >>> Am I doing the 1-1 thing that BDD specifically set out to avoid? >> >> 1-1 example per method is probably a red flag, but 1-1 spec file per >> implementation file makes navigation easier, so I think it's actually >> a good thing. >> >> The underlying problem with 1-1 mappings stems from IDE's that will >> make an empty test case by reflecting on an untested object. You'd end >> up with 50 line long test methods named "testGetName" that actually >> contain 20 different tests in the one method. That's an extreme, but I >> used to see that sort of thing all the time when I was consulting, and >> it makes it very difficult to understand what is being tested and what >> went wrong when there is a failure. >> >> Make sense? >> >> - David >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> Quoting Adam Sroka <adam.sr...@gmail.com>: >>> >>>> On Tue, Feb 2, 2010 at 9:53 PM, Andrei Erdoss <erd...@gmail.com> wrote: >>>>> >>>>> Hello Frank, >>>>> >>>>> From my understanding these are the roles of should_receive and stub. >>>>> >>>>> should_receive checks to make sure that a method or a property is >>>>> called. >>>>> To >>>>> this you can specify the arguments that it gets called (.with()), what >>>>> it >>>>> returns (.and_return) and how many times this happens (.once, .twice >>>>> etc). >>>>> >>>>> stub on the other hand is a place holder for functions calls that have >>>>> been >>>>> tested already or are Rails defaults, which don't need to be tested. >>>>> stubs >>>>> are used in conjunction with mock_models, in order to provide for the >>>>> functions or properties that are needed for the code to run, up to the >>>>> test >>>>> point. >>>>> >>>> >>>> I think that it is best to think of these in terms of command query >>>> separation. In case you aren't familiar with that principle, it states >>>> that some methods are commands - they tell an object to do something >>>> but don't return anything interesting, and other methods are queries - >>>> they return some interesting value but have no side effects. >>>> >>>> should_receive is how we set an expectation for a command. We don't >>>> really care what a command returns but we do care that it gets called. >>>> should_receive literally says that the command should be called with >>>> the given parameters. >>>> >>>> stub is how we handle a query. We care what a query returns, or rather >>>> the code we are testing does, but we don't really care when it gets >>>> called (or how often) per se. If we depend on its result then it >>>> should be called, but the effect that the result has on the system >>>> we're testing is what we really care about. >>>> _______________________________________________ >>>> rspec-users mailing list >>>> rspec-users@rubyforge.org >>>> http://rubyforge.org/mailman/listinfo/rspec-users >>>> >>> >>> >>> >>> _______________________________________________ >>> rspec-users mailing list >>> rspec-users@rubyforge.org >>> http://rubyforge.org/mailman/listinfo/rspec-users >>> >> _______________________________________________ >> rspec-users mailing list >> rspec-users@rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users >> > > > > _______________________________________________ > rspec-users mailing list > rspec-users@rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users > _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users