Monday, December 28, 2009

Re: testing a controller's add action

Lorenzo Bettini <bett...@dsi.unifi.it> wrote:
> I'm not getting errors: as I said before, I can see that data is not
> populated using the debugger, and also because it executes the
> instructions to be executed when data is null; thus it basically does
> not faulter, it simply does not get any data...  can it be a bug?

It's possible, I never had a whole lot of luck with testAction other
than just really basic tests, as such I almost never use it. It's
possible we're missing something really simple. /shrug. testAction
does a lot of the 'magic' on it own, but I prefer doing things in such
a way I have complete control over the test -- less surprises that
way. I read, in 1.3/2.0 the testsuite is getting a major makeover.

> yes, with the instructions in this post I can successfully test mycontroller'sadd and edit actions.
>
> But I guess the documentation of cakephp should be updated to include
> such way oftestingcontrollers, especially since testAction, as you
> also noticed, is not powerful enough (and probably buggy due to the
> missing data ;)

I agree, I like the way Mark tests his controllers, it makes a lot
more sense to me. If you're feeling generous go ahead and post an
alternative in the Book, they always like people helping them make the
documentation better.

> what do you mean by Mocking the Auth Component?

Well, instead of using the actual Auth Component, you'd use a Mocked
stub of that component with "dummy" functions you can set to return
whatever you want. SimpleTest comes with a great Mocking Class that
does all the work for you. A simple Mock would look something like
this:

App::import('Component', 'Auth');
App::import('Controller', 'SomeController');

function startTest(){
$this->SomeController = new TestSomeController();
$this->SomeController->Components->initialize($this-
>SomeController);
Mock::generate('AuthComponent');
$this->SomeController->Auth = new MockAuthComponent();
}

That little setup will overwrite the Auth of your Controller with the
Mocked Auth generated by Mock::generate('string_of_class_to_mock').
The mock creates a dummy class that has all the same methods as the
actual class but everything returns null by default. So what's the
point? Well, you can change what the MockAuthComponent's functions
return on the fly to better suite your tests.

Here's an example, lets say in your controller you're doing something
like:

//In SomeController action...
$stuff = $this->SomeModel->findByUserId($this->Auth->user('id'));
$this->set('stuff', $stuff);

In you're test you can decide what $this->Auth->user('id') returns
without touching the Auth.User.id in the session.

//Back in the test...
function testSomeAction(){
$this->SomeController->Auth->setReturnValue('user',1); //$this->Auth-
>user(...) will return 1.
$this->SomeController->someAction();
$this->assertTrue(!empty($this->SomeController->viewVars
['stuff'])); //Assert that the stuff variable has something in it.
}

As you can see, we never had to write Auth.User.id to the session to
get the desired result. This is a much more focused test than what
Mark suggests in the link I gave you in my previous post. This test
really hones in on the action, not the auth component as well.

You can do a whole lot with mocks, like only mock certain functions
and letting the other ones be. Here is the documentation:
http://www.simpletest.org/en/mock_objects_documentation.html


Hope that helps,
Happy testing,
Nick
http://www.webtechnick.com


> > On Dec 27, 2:28 am, Lorenzo Bettini <bett...@dsi.unifi.it> wrote:
> >> Yes, it uses a redirect (inside the method), but the problem comes up
> >> before reaching a possible redirect: empty($this->data) is true when
> >> entering the method itself...
>
> >> As for the redirect I think I already handle that with
>
> >> class TestPapers extends PapersController {
> >>         var $autoRender = false;
>
> >>      function redirect($url, $status = null, $exit = true) {
> >>          $this->redirectUrl = $url;
> >>      }
>
> >> but the problem, as I said, it's that no data is passed to theaction...
>
> >> John Andersen wrote:
> >>> Is your addactionusing a redirect?
> >>>    John
> >>> On Dec 26, 6:48 pm, Lorenzo Bettini <bett...@dsi.unifi.it> wrote:
> >>>> Hi
> >>>> I already managed to test some actions of controllers using testAction
> >>>> method; these were actions that were expected to return something.
> >>>> Now, I'd like to test an addactionof thecontroller, thus, following
> >>>> the book I did:
> >>>> $data = array(
> >>>>         'Paper' => array(
> >>>>                 'title' => 'MyTitle',
> >>>>                 'year' => 2009
> >>>>         ));
> >>>> debug($data);
> >>>> $results = $this->testAction(
> >>>>         array(
> >>>>         'controller' => 'papers',
> >>>>         'action' => 'admin_add',
> >>>>         ),
> >>>>         array('data' => $data, 'method' => 'post')
> >>>>         );
> >>>> but when executing thecontroller'saction(I tried that with the
> >>>> debug), the $this->data is always empty and uninitialized...  where am I
> >>>> going wrong?
> >>>> thanks in advance
> >>>>         Lorenzo
> >> --
>
> --
> Lorenzo Bettini, PhD in Computer Science, DI, Univ. Torino
> HOME:http://www.lorenzobettini.itMUSIC:http://www.purplesucker.com
> BLOGS:http://tronprog.blogspot.com http://longlivemusic.blogspot.com

Check out the new CakePHP Questions site http://cakeqs.org and help others with their CakePHP related questions.

You received this message because you are subscribed to the Google Groups "CakePHP" group.
To post to this group, send email to cake-php@googlegroups.com
To unsubscribe from this group, send email to
cake-php+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/cake-php?hl=en

No comments: