Testy jednostkowe, jak sama nazwa wskazuje, polegają na testowaniu jednostki - jednego obiektu w ramach jednego zestawu testów. Co jednak w sytuacji, gdy testowany obiekt jest zależny od innego obiektu? Przy bezpośrednim wykorzystaniu tego dodatkowego obiektu w testach jednostkowych jest łamana podstawowa ich zasada. Przy wykorzystaniu rzeczywistego obiektu pomocniczego, robimy ślepe założenie, że działa on prawidłowo i nie zakłóci on wyników testów. Innymi słowy testy mogą się nie powieść, ale nie oznacza to jednoznacznie, że to w testowanej klasie jest błąd. Sytuacja może się również paradoksalnie odwrócić, testy zostaną przeprowadzone prawidłowo, mimo iż testowana klasa zawiera błędy, które powinny zostać wykryte.
Jedno z rozwiązań tego problemu przedstawiłem w poprzednim wpisie na temat wzorca Service Stub. Teraz postaram się pokazać inne podejście, a mianowicie wykorzystanie obiektów Mock.
Zazwyczaj test wygląda tak, że wywołujemy operacje na obiekcie testowanym, a następnie przeprowadzamy asercje na stanie tego obiektu - nazywa się to weryfikacją stanu. Inne podejście do testowania mówi o testowaniu zachowania danego obiektu, a nie jego stanu - interesuje nas nie to, czy po wywołaniu metody prawidłowo zmienił się stan obiektu, ale to czy obiekt ten zachował się prawidłowo.
Prosty przykład oprę na chyba najprostszej z możliwych implementacji wzorca Composite:
[PHP]- class Composite
- {
- private $parent;
- private $children = array();
-
- private function setParent(Composite $parent)
- {
- $this->parent = $parent;
- }
-
- public function addChild(Composite $child)
- {
- if ($child->getParent()) {
- $child->getParent()->remove($child);
- }
-
- $child->setParent($this);
- $this->children[] = $child;
- }
-
- public function remove(Composite $child)
- {
- $index = $this->findChildIndex($child);
-
- if ($index !== null)
- {
- unset($this->children[$index]);
- return true;
- }
-
- return false;
- }
-
- public function getChildren()
- {
- return $this->children;
- }
- }
Chcemy przetestować dodawanie potomków, tak więc na początku sprawdzamy ile potomków ma testowany obiekt, dodajemy obiekt i ponownie sprawdzamy liczbę potomków:
[PHP]- class CompositeTest extends PHPUnit_Framework_TestCase
- {
- private $composite;
-
- public function setUp()
- {
- $this->composite = new Composite();
- }
-
- public function testAddingChildren()
- {
- $this->assertEquals(0, count($this->composite->getChildren()));
-
- $child = new Composite();
- $this->composite->addChild($child);
-
- $this->assertEquals(1, count($this->composite->getChildren()));
- }
- }
W tym teście interesuje nas efekt, czyli to czy po dodaniu dziecka faktycznie stan testowanego obiektu się zmienił.
Przy wykorzystaniu obiektu Mock weryfikujemy to, w jaki sposób zachował się testowany obiekt. Sprawdzamy, czy wywołał on określoną liczbę razy odpowiednie metody obiektu Mock. W naszym przypadku sprawdzamy, czy metody getParent oraz setParent zostały wywołane dokładnie po jednym razie na rzecz obiektu dziecka.
[PHP]- //ciach...
- public funciton testAddingChildrenByMockObject()
- {
- $mock = $this->getMock('Composite', array('getParent', 'setParent'));
- $mock->expects($this->once())//spodziewamy się wywołania dokładnie raz metody getParent, zwróci ona false
- ->method('getParent')
- ->will($this->returnValue(null));
- $mock->excepts($this->once())//spodziewamy się wywołania dokładnie raz metody setParent
- ->method('setParent');
-
- $this->composite->addChildren($mock);
- }
Czytaj dalej tutaj (rozwija treść wpisu)
Czytaj dalej na blogu autora...
Zwiń
Czytaj na blogu autora...