Saya punya masalah aneh dengan Laravel 5 dan PHPUnit. Ketika saya mencoba meniru fasad Laravel (mis. Auth, View, Mail) saya selalu mendapatkan pengecualian ini:
Mockery\Exception\InvalidCountException: Metode send(emails.register, array('user'=›'object(MCC\Models\Users\User)',), object(Closure)) dari Mockery_0_Illuminate_Mail_Mailer harus dipanggil tepat 1 kali tetapi dipanggil 0 kali.
Saya punya masalah dengan bagian "should be called exactly 1 times but called 0 times."
. Ini adalah kode pengujian saya:
public function testSendEmailToNewUserListener()
{
$user = factory(MCC\Models\Users\User::class)->create();
Mail::shouldReceive('send')
->with(
'emails.register',
['user' => $user],
function ($mail) use ($user) {
$mail->to($user->email, $user->name)
->subject('Thank you for registering an account.');
}
)
->times(1)
->andReturnUsing(function ($message) use ($user) {
dd($message);
$this->assertEquals('Thank you for registering an account.', $message->getSubject());
$this->assertEquals('mcc', $message->getTo());
$this->assertEquals(View::make('emails.register'), $message->getBody());
});
}
Saya menutup dd($message)
karena saya ingin mengetahui detail tentang nilai pengembalian (tampilan $message->getTo()
).
Kelas TestCase saya:
<?php
/**
* Provides default values for functional tests.
*
* Class TestCase
*/
abstract class TestCase extends Illuminate\Foundation\Testing\TestCase
{
/**
* The base URL to use while testing the application.
*
* @var string
*/
protected $baseUrl = 'http://004-mcc.dev';
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require __DIR__ . '/../bootstrap/app.php';
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
\Illuminate\Support\Facades\Mail::pretend(TRUE);
return $app;
}
}
Phpunit.xml saya:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="Application Test Suite">
<directory>./tests/</directory>
</testsuite>
<testsuite name="User">
<directory>./tests/UserRepository</directory>
</testsuite>
<testsuite name="User/Auth">
<directory>./tests/UserRepository/Auth</directory>
</testsuite>
<testsuite name="User/User">
<directory>./tests/UserRepository/User</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">app/</directory>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="local"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
</php>
</phpunit>
Saya memeriksa banyak sumber dari Google, dari Stackoverflow, yang disebutkan kebanyakan orang
$this->app->instance('Illuminate\Mail\Mailer', $mockMailer)
tetapi bahkan instruksi ini tidak membantu. Sebagian besar pertanyaan tentang masalah ini tidak terpecahkan. Saya memeriksa ekstensi yang terpasang, Laravel saya baru diinstal (beberapa model, beberapa rute, sekitar 20 tes).
Saya juga mencoba metode seperti
->atLeast()
->times(1)
or
->atLeast()
->once()
tapi tidak ada yang berfungsi dengan baik. Juga sebagai gantinya
Mail::shouldReceive('mail')
saya menggunakan
$mailMock = Mockery::mock('Illuminate\Mail\Mailer');
$mailMock->shouldReceive('mail)
tetapi cara-cara ini masih tidak berhasil.
Log konsol lainnya:
/home/grzgajda/programowanie/php/005mcc/vendor/mockery/mockery/library/Mockery/CountValidator/Exact.php:37
/home/grzgajda/programowanie/php/005mcc/vendor/mockery/mockery/library/Mockery/Expectation.php:271
/home/grzgajda/programowanie/php/005mcc/vendor/mockery/mockery/library/Mockery/ExpectationDirector.php:120
/home/grzgajda/programowanie/php/005mcc/vendor/mockery/mockery/library/Mockery/Container.php:297
/home/grzgajda/programowanie/php/005mcc/vendor/mockery/mockery/library/Mockery/Container.php:282
/home/grzgajda/programowanie/php/005mcc/vendor/mockery/mockery/library/Mockery.php:142
/home/grzgajda/programowanie/php/005mcc/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:48
/home/grzgajda/.composer/vendor/phpunit/phpunit/src/TextUI/Command.php:148
/home/grzgajda/.composer/vendor/phpunit/phpunit/src/TextUI/Command.php:100
Saya juga menemukan satu saran bagus (di sana Stackoverflow) tetapi tidak berhasil.
Mockery secara default adalah perpustakaan yang mematikan, bukan perpustakaan yang mengejek (yang membingungkan karena namanya).
Artinya -›shouldReceive(...) secara default adalah nol kali atau lebih. Saat menggunakan -›once(), Anda mengatakan itu harus dipanggil nol atau satu kali, tetapi tidak lebih. Artinya, hal itu akan selalu berlalu.
Saat Anda ingin menegaskan bahwa ini dipanggil satu kali, Anda dapat menggunakan -›atLeast()-›times(1) (satu kali atau lebih) atau -›times(1) (tepat satu kali)
Versi php saya: PHP 5.6.14-1+deb.sury.org~trusty+1 (cli)
Apache saya: Server version: Apache/2.4.16 (Ubuntu)
Versi ejekan (dari komposer): "mockery/mockery": "0.9.*"
Kerangka kerja Laravel (dari komposer): "laravel/framework": "5.1.*"