2009-10-26 16 views
0

La question courte:Y a-t-il un moyen de réinitialiser un objet Mock dans SimpleTest, en supprimant toutes les attentes?Objets Simples SimpleTest: suppression des attentes

explication plus longue:

J'ai une classe que je teste en utilisant SimpleTest et je rencontre un problème avec les objets Mock qu'il utilise.

La classe est un Logger, et à l'intérieur de l'enregistreur sont un certain nombre d'objets (WriterFileWriter, EmailWriter, etc.). L'appel de la méthode Logger::log() exécute une certaine logique dans les coulisses et achemine le message vers le programme d'écriture correct. Les auteurs sont mis en cache dans la classe Logger pour éviter de les ré-instancier chaque fois à chaque fois.

Dans mes tests unitaires, j'ai configuré un Logger, créé et ajouté des objets Mock Writer, puis utilisé des méthodes telles que MockDBWriter->expectOnce() pour tester le fonctionnement du Logger.

Le problème est maintenant que je veux tester une autre fonction du Logger, mais les attentes expectOnce sont toujours en vigueur et provoquent l'échec de mes tests suivants.

function testWritesMessageOK() { 
    $log = Logger::getInstance(); 
    $mock = new MockFileWriter($this); 

    $log->addWriter($mock); 

    $mock->expectOnce("write", "Message"); 

    $log->write("Message"); // OK 
} 

// this is just an example - the actual test is much less inane 
function testNumberOfWrites() { 
    $log = Logger::getInstance(); 
    $mock = $log->getWriter(); 

    $mock->expectCallCount('write', 2); 

    $log->write("One"); // fail - it doesn't match "Message" 
    $log->write("Two"); 
} 

est-il un moyen de réinitialiser un objet Mock, en supprimant toutes les attentes?

Répondre

2

Utilisez des instances de simulation distinctes.

Soit:

$mock = $log->getWriter(); 
$mock = new $mock; 

Ou:

$mock = new MockFileWriter($this); 
// And then: 
$mock = new MockDBWriter($this); 
// And then: 
$mock = new MockEmailWriter($this); 
// etc. 

Je remets en question la sagesse des écrivains de mise en cache pour sauver re-instanciation. Si vous instanciez une opération bon marché (ne créez pas de connexion DB ou quoi que ce soit) et reportez ce type de chose jusqu'à ce que vous ayez vraiment besoin de la connexion, comme la première requête, vous n'aurez pas besoin de mettre en cache. allez-vous en.

L'autre chose que vous pouvez faire est d'appeler le constructeur SimpleMock.

$mock = $log->getWriter(); 
$mock->SimpleMock(); 

qui fera tout cela:

/** 
* Creates an empty action list and expectation list. 
* All call counts are set to zero. 
* @access public 
*/ 
function SimpleMock() { 
    $this->_actions = &new SimpleCallSchedule(); 
    $this->_expectations = &new SimpleCallSchedule(); 
    $this->_call_counts = array(); 
    $this->_expected_counts = array(); 
    $this->_max_counts = array(); 
    $this->_expected_args = array(); 
    $this->_expected_args_at = array(); 
    $test = &$this->_getCurrentTestCase(); 
    $test->tell($this); 
} 

Le seul problème avec cela est que tell() appel à la fin qui fera l'SimpleMock::atTestEnd() à appeler deux fois quand récoltant les attentes. Mais, vous pouvez corriger cela avec ceci:

// $this should == the test case in question 
array_pop($this->_observers); 

Cette réponse est basée sur la version 1.0.1 de SimpleTest.