Ich teste einen Symfony-Befehl, um Erinnerung Textnachrichten zu senden. Dafür habe ich einen Dienst für meine SMS-Schnittstelle und bin spöttisch den Behälter sowie den Text-Messaging-Dienst erstellt:
Die Funktion im Test
protected function textReminders()
{
$mailer = $this->getContainer()->get('mailer');
$em = $this->getContainer()->get('doctrine')->getManager();
if ($this->getContainer()->get('kernel')->getEnvironment() == 'dev'){
$debug = true;
}else{
$debug = false;
}
$textMessage = $this->getContainer()->get('text_messaging.interface');
$textMessage->sendSMS($target, $content, $debug);
}
-Test
private function getMockContainer()
{
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\Container')
->disableOriginalConstructor()
->setMethods(array('get'))
->getMock();
return $container;
}
protected function setupMocks()
{
$mockText = $this->getMockBuilder('TextaHQ')
->disableOriginalConstructor()
->setMethods(array('sendSMS'))
->getMock();
$mockContainer = $this->getMockContainer();
$container = self::$kernel->getContainer();
$mockContainer->method('get')
->withConsecutive(['mailer'], ['doctrine'], ['kernel'], ['text_messaging.interface'])
->willReturnOnConsecutiveCalls(
$this->returnValue($container->get('mailer')),
$this->returnValue($container->get('doctrine')),
$this->returnValue(self::$kernel),
$this->returnValue($mockText))
;
$this->setMyMock([
'text' => $mockText,
'container' => $mockContainer
]);
}
public function testExecute()
{
$this->setupMocks();
self::bootKernel();
$application = new Application(self::$kernel);
$application->add(new ActionRemindCommand());
$command = $application->find('ahp:remind');
$command->setContainer($this->getMyMock()['container']);
$commandTester = new CommandTester($command);
$commandTester->execute(array(
'command' => $command->getName(),
'type' => 'text'
));
$output = $commandTester->getDisplay();
$this->assertions();
}
protected function assertions()
{
$this->getMyMock()['text']
->expects($this->once())
->method('sendSMS')
;
}
Aktualisierter Test, alles in einer Datei
public function testExecute()
{
$insertSql = 'echo "'
. str_replace(
array('"' ,'`' ),
array('\\"' ,'\\`'),
$this->getPrepSql())
. '" | mysql ahp_example_com';
exec($insertSql);
self::bootKernel();
$mockText = $this->getMockBuilder('TextaHQ')
->disableOriginalConstructor()
->setMethods(array('sendSMS'))
->getMock();
$mockContainer = $this->getMockBuilder('Symfony\Component\DependencyInjection\Container')
->disableOriginalConstructor()
->setMethods(array('get'))
->getMock();
$container = self::$kernel->getContainer();
$mockContainer->method('get')
->withConsecutive(['mailer'], ['doctrine'], ['kernel'], ['text_messaging.interface'])
->willReturnOnConsecutiveCalls(
$this->returnValue($container->get('mailer')),
$this->returnValue($container->get('doctrine')),
$this->returnValue(self::$kernel),
$this->returnValue($mockText))
;
$application = new Application(self::$kernel);
$application->add(new ActionRemindCommand());
$mailer = self::$kernel->getContainer()->get('swiftmailer.mailer');
$logger = new \Swift_Plugins_MessageLogger();
$mailer->registerPlugin($logger);
$this->setMailCollector($logger);
$output = '';
for($i=1;$i<=$this->getRunNoTimes();$i++) {
$command = $application->find('ahp:remind');
$command->setContainer($mockContainer);
$commandTester = new CommandTester($command);
$commandTester->execute(array(
'command' => $command->getName(),
'type' => 'text'
));
$output .= $commandTester->getDisplay();
}
$mockText
->expects($this->once())
->method('sendSMS')
;
}
** PhpStorm Testanruf **
/usr/bin/php /home/jochen/projects/ahp/trunk/vendor/phpunit/phpunit/phpunit --configuration /home/jochen/projects/ahp/trunk/app/phpunit.xml.dist AgriHealth\AhpBundle\Tests\Command\ActionRemindCommandVet7DaysBeforeTest /home/jochen/projects/ahp/trunk/src/AgriHealth/AhpBundle/Tests/Command/RemindText/ActionRemindCommandVet7DaysBeforeTest.php --teamcity
Testing started at 10:25 AM ...
PHPUnit 5.5.4 by Sebastian Bergmann and contributors.
Expectation failed for method name is equal to <string:sendSMS> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
Time: 1.12 seconds, Memory: 18.00MB
FAILURES!
Tests: 1, Assertions: 1, Failures: 1.
Process finished with exit code 1
Wenn ich den Test debuggen, kann ich sehen, dass $ Textm ein Mock ist.
jedoch am Ende des Tests in Behauptungen(), erhalte ich eine Fehlermeldung:
Expectation failed for method name is equal to <string:sendsms> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
Der Debugger zeigt die verspottete Funktion als Kleinbuchstaben: „sendsms“, aber die Funktion Umbenennung hat nicht geholfen.
sieht aus wie Ihre Mock-Konfiguration fällt aus 'testExecute' Bereich bedeutet, dass Sie Ihre Mocks nicht über '$ this-> setMyMock()' speichern und später mit '$ this-> getMyMock()' für die Assertion extrahieren können. PHPUnit kann die Aufrufe nicht verfolgen. Weitere Details: [Nur Mock-Objekte erzeugt im Rahmen eines Tests wird von PHPUnit automatisch verifiziert.] (https://phpunit.de/manual/current/en/test-doubles.html#test-doubles.mock-objects) – xmike
Ich habe es so gemacht Möglichkeit, die Erstellung der Mock-Objekte zu zentralisieren und die Ausführung für eine Gruppe von Tests zu testen. Nur die Eingabedaten und das Ergebnis ändern sich für jeden Test. Ist das nicht möglich? Muss ich es immer wieder wiederholen? – jdog
um genauer zu sein: Sie können Instanzen Ihrer Mock-Objekte erstellen und einige allgemeine Konfigurationen außerhalb von 'testMethod' vornehmen, aber alle Erwartungen müssen innerhalb von' testMethod' definiert werden. Das liegt daran, dass PHPUnit solche Erwartungen an diese 'testMethod' bindet (wenn' testMethod' aufgerufen wird, werden alle Erwartungen für diese Methode als erwartet registriert). – xmike