问题描述
我想测试调用createuserProivder()
方法时的Auth外观是否返回我的用户提供程序。
问题在于,使用以下代码以及注释掉的部分,AuthManager仍然是原始版本,而不是模拟版本。
对于未注释的部分,我得到一个错误:Mockery\Exception\BadMethodCallException : Method Mockery_2_Illuminate_Auth_AuthManager::validate() does not exist on this mock object
我不知道如何测试。
我想测试一种自定义防护行为,该行为在调用Guard的validated()
方法时调用UserProvider,因此,我需要模拟Auth外观,因为它是返回User Provider的外观。
public function testUserIsAuthenticatedWhenUserProviderFindsCredentialsmatch()
{
$userId = Uuid::uuid();
$user = new User($userId);
$userProvider = new UserProvider($user);
// $this->partialMock(AuthManager::class,function ($mock) use ($userProvider) {
// $mock->shouldReceive('createuserProvider')
// ->once()
// ->andReturn($userProvider);
// });
Auth::shouldReceive('createuserProvider')
->once()
->andReturn($userProvider);
$result = $this->app['auth']->validate(['dummy' => 123]);
测试方法:
/**
* @param array $credentials
* @return bool
*/
public function validate(array $credentials = []): bool
{
$this->user = $this->provider->retrieveByCredentials($credentials);
return (bool)$this->user;
}
服务提供商:
class LaravelServiceProvider extends AuthServiceProvider
{
/**
* Register any application authentication / authorization services.
*
* @return void
*/
public function boot()
{
Auth::extend(
'jwt',function ($app,$name,array $config) {
$moduleConfig = $app['config'];
return new JWTAuthGuard(
Auth::createuserProvider($config['provider']),$this->app['request'],new JWTHelper()
);
}
);
}
}
解决方法
仅仅是因为您创建了模拟类,并不意味着它会在服务容器中自动替换。身份验证管理器绑定为单例,因此您可以使用以下命令更新服务容器中的共享实例:
$mock = $this->partialMock(AuthManager::class,function ($mock) use ($userProvider) {
$mock->shouldReceive('createUserProvider')
->once()
->andReturn($userProvider);
});
$this->app->instance('auth',$mock);
$result = $this->app['auth']->validate(['dummy' => 123]);
...
,
经过大量调试后,我发现了可以执行此操作的地方:
ALT_MSG_MAP
不过,另一种方法是只在Tests目录中创建一个UserProvider进行测试:
protected function getEnvironmentSetUp($app)
{
$this->mockUserProvider($app);
}
protected function mockUserProvider($app)
{
$userId = Uuid::uuid();
$user = new User($userId);
$userProvider = new UserProvider($user);
$mock = Mockery::mock(AuthManager::class)->makePartial();
$reflection = new ReflectionClass($mock);
$reflection_property = $reflection->getProperty('app');
$reflection_property->setAccessible(true);
$reflection_property->setValue($mock,$app);
$mock
->shouldReceive('createUserProvider')
->andReturn($userProvider);
$app->instance('auth',$mock);
}
然后在测试文件中
class TestUserProvider extends AuthServiceProvider
{
/**
* Register any application authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Auth::provider(
'TestProvider',function ($app,array $config) {
return new UserProvider();
}
);
}
}