[PHP/ZF] Unittests voor MVC model

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • storeman
  • Registratie: April 2004
  • Laatst online: 11:48
Ik ben laatst PHPUnit tegen gekomen voor het unittesten, dit leek me zeer interessant en ben er maar eens ingedoken.

Mijn vraag is redelijk specifiek, dus ik hoop dat iemand me een schop in de goede richting kan geven.

Ik wil dus mijn MVC applicatie gaan testen met de Zend_Test extensie van het Zend Framework. Deze Zend_Test module maakt gebruik van PHPUnit wat ik geinstalleerd heb en wat functioneel is.

Nu heb ik in mijn IndexTest.php de volgende test:
PHP:
1
2
3
4
5
6
    public function testCallWithoutActionShouldIdentifyUser()
    {
        $this->dispatch('/');
        $this->assertController('user');
        $this->assertAction('identify');
    }

Deze gaat prima en verwijst netjes naar de juiste controller en action. Deze wordt afgevangen door een Front controller plugin en de module/controller/action worden gewijzigd in het request opbject.


Maar als ik de loginAction aanroep op de usercontroller, dan zou deze moeten verwijzen naar de identifyAction, hiervoor wordt de redirector helper gebruikt.
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//In de loginAction
$request = $this->getRequest();
        
if( !$request->isPost() ){
    $this->_helper->redirector('identify');
}
// render de view enzo....
//...
//..

// Een andere test
public function testNoPostDataLoginShowRedirect()
{
    // Should redirect without post
    $this->dispatch('/user/login');
    $this->assertRedirectTo('/user/identify');
}


Deze laatste test geeft een fout, er schijnt namelijk niet verwezen te worden naar een andere locatie.

Nu heb ik nog wat experimenten gedaan om het probleem te vinden:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Alles getest met de Zend_Test...::assertRedirectTo functie
// ...
// Werkt
public function index1Action(){
    $this->_helper->redirector('identify');
}

// Werkt niet
public function index2Action(){
    if( $this->_request->isPost() ){
        $this->_helper->redirector('identify');
    }
    
    // Do other stuff and render view
}

// Werkt
public function index3Action(){
    if( $this->_request->isPost() ){
        $this->_helper->redirector('identify');
        return null;
    }
    
    // Do other stuff and render view
}

// PHPUnit crasht en geeft resultaten van voorgaande tests, maar niet van de huidige.
//  ook wordt de test niet afgerond, want het resultaat overzicht wordt niet getoond (Geslaagd/Gefaald)
public function index3Action(){
    if( $this->_request->isPost() ){
        $this->_helper->redirector->gotoSimpleAndExit('identify');
    }
    
    // Do other stuff and render view
}

"Chaos kan niet uit de hand lopen"


Acties:
  • 0 Henk 'm!

  • OxiMoron
  • Registratie: November 2001
  • Laatst online: 08-07 14:27
Heb je ook gewoon zelf in je browser gekeken of hij wel redirect?

En probeer eens een return te geven na de redirect, het kan zijn dat hij eerst de hele view zooi doet voordat hij redirect.

Albert Einstein: A question that sometime drives me hazy: Am I or are the others crazy?


Acties:
  • 0 Henk 'm!

  • storeman
  • Registratie: April 2004
  • Laatst online: 11:48
OxiMoron schreef op woensdag 21 januari 2009 @ 16:34:
Heb je ook gewoon zelf in je browser gekeken of hij wel redirect?

En probeer eens een return te geven na de redirect, het kan zijn dat hij eerst de hele view zooi doet voordat hij redirect.
Uiteraard heb ik getest, alle redirects werken zoals bedoelt en die view wordt niet verstuurd.

Wat wel opvallend is, dat de header die wordt teruggestuurd tijdens de PHPUnit een code 500 is (server error), máár dat er wel een redirect heeft plaatsgevonden. De header bevat namelijk ook:
'Location: /user/identify'

Terwijl dit in de browser gewoon prima gaat. Met firebug zie ik een nette code 302 redirect naar de juiste pagina.

[ Voor 4% gewijzigd door storeman op 21-01-2009 16:57 . Reden: kleine aanvulling ]

"Chaos kan niet uit de hand lopen"


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

OxiMoron schreef op woensdag 21 januari 2009 @ 16:34:
Heb je ook gewoon zelf in je browser gekeken of hij wel redirect?
Het idee van een unit test is juist dat je geen browser nodig hebt. Je bent namelijk bezig met component (unit) based programming. Je voert het component wat input en vervolgens controleer je of de output (actie) gewenst is (de assert vergelijkingen).

Het MVC pattern is bij uitstek geschikt om offline te testen omdat je namelijk de controller test. Bij de meeste MVC implementaties kan de controller verschillende acties terug geven en een redirect actie is er daar eentje van.
En probeer eens een return te geven na de redirect, het kan zijn dat hij eerst de hele view zooi doet voordat hij redirect.
Maar waarom zou een je controller een view laten renderen als de gewenste aktie een redirect is?

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • storeman
  • Registratie: April 2004
  • Laatst online: 11:48
Niemand_Anders schreef op woensdag 21 januari 2009 @ 17:01:

Maar waarom zou een je controller een view laten renderen als de gewenste aktie een redirect is?
Inderdaad, als ik een return null doe, dan werkt het dus wel (zoals ook in mijn startpost), maar dat vind ik de grootste onzin.

Die redirectAndExit geeft nog een ander resultaat, in de browser werkt het dus wel goed, maar de test struikelt over de exit() die wordt aangeroepen in de redirectAndExit functie.

"Chaos kan niet uit de hand lopen"


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Ik ben alleen bekend met MVC frameworks in C# (zoals MonoRail en ASP.NET MVC). Ik ken dus niet de specifieke mogelijkheden van het Zend MVC framework, maar bij de meeste frameworks is ook het renderen van een view een (default) aktie.

Het retourneren van null (bij door mij gebruikte frameworks) bij een redirect aktie staat gelijk aan een NoOp aktie. Uit je verhaal begrijp ik dat Zend MVC null vergelijkbaar verwerkt.

Wat betreft redirectAndExit denk ik dat je even moet kijken naar de response headers. Aangezien de redirect of het renderen van een view het resultaat is van de aktie (return Redirect()) is dat altijd het laatste statement vind ik een aktie als redirectAndExit een beetje vreemd.

Aangezien de redirector via een helper wordt aangeroepen vermoed ik dat de redirectory alleen de 'location' header zet en dat redirectAndExit tevens de exit methode aanroept. Maar ik denk dat je even in de unittest documentatie moet opzoeken hoe de unittests omgaan met Exit() en Die() methods..

En anders zul je voor de zekerheid de index3Action methode aanhouden (return null). Van alle index akties vind ik deze het meest duidelijk.

If it isn't broken, fix it until it is..

Pagina: 1