On Wed, Feb 3, 2010 at 2:07 PM, <[email protected]> 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 '#[email protected]}'"
redirect_to somewhere
else
render :new
end
end
Cheers,
-foca
>
> Once again, thanks++
> Frank
>
>
> Quoting David Chelimsky <[email protected]>:
>
>> On Wed, Feb 3, 2010 at 8:52 AM, <[email protected]> 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")
>>> �[email protected]_receive(:clients).and_return @clients
>>> end
>>>
>>> describe "when client is found" do
>>>
>>> before do
>>> �...@client = mock_model(Client)
>>> �[email protected]_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 = []
>>
>>> �[email protected]_receive(:projects).and_return @projects
>>> �...@project = mock_model(Project)
>>> �[email protected]_receive(:build).and_return @project
>>> �[email protected]_receive(:save).and_return true
>>> �[email protected]_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: #[email protected]}"
>>> 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 <[email protected]>:
>>>
>>>> On Tue, Feb 2, 2010 at 9:53 PM, Andrei Erdoss <[email protected]> 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
>>>> [email protected]
>>>> http://rubyforge.org/mailman/listinfo/rspec-users
>>>>
>>>
>>>
>>>
>>> _______________________________________________
>>> rspec-users mailing list
>>> [email protected]
>>> http://rubyforge.org/mailman/listinfo/rspec-users
>>>
>> _______________________________________________
>> rspec-users mailing list
>> [email protected]
>> http://rubyforge.org/mailman/listinfo/rspec-users
>>
>
>
>
> _______________________________________________
> rspec-users mailing list
> [email protected]
> http://rubyforge.org/mailman/listinfo/rspec-users
>
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users