问题描述
你好,我的考试有问题。 我正在尝试测试通过UserDto数据创建UserObject的UserFactory。 我不知道如何测试它,因为工厂需要依赖项中的PasswordEncoder。
use App\Entity\User;
use App\Service\Factory\UserFactory;
use PHPUnit\Framework\MockObject\MockObject as MockObject;
use PHPUnit\Framework\TestCase;
class UserFactoryTest extends TestCase
{
/**
* @covers UserFactory
*/
public function testShouldcreateuserObjectFromUserDto()
{
//Given
/**
* @var UserDto | MockObject
*/
$userDto = $this->getMockBuilder(UserDto::class);
//When
$userFactory = new UserFactory(/* PASSWORD ENCODER */);
$user = $userFactory->create($userDto);
//Then
$this->assertInstanceOf(User::class,$user);
}
}
namespace App\Service\Factory;
use App\Entity\User;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class UserFactory
{
/**
* @var UserPasswordEncoderInterface
*/
private $encoder;
public function __construct(UserPasswordEncoderInterface $encoder)
{
$this->encoder = $encoder;
}
public function create(UserDto $dto)
{
$user = new User();
$user->setPassword($this->encoder->encodePassword($dto->plainPassword));
/**
* CODE..
*/
return $user;
}
}
这是对的吗?我如何测试具有依赖性的工厂? 我无法在我的TestClass中使用__construct
解决方法
(提示:显然您使用的是UserPasswordEncoderInterface错误,因为它不是PasswordEncoderInterface-前者还希望将User作为参数,而后者则不是,我今天才学到,您可能想解决这个问题)
通常,您必须为要测试的类提供所有依赖关系。本质上,有不同的方法:实现接口的简化版本(如果是接口),实际找到依赖项并将其实例化,或使用模拟并告诉它将会发生什么。如果您通常知道依赖项会发生什么(非黑盒测试),则可以完成后者。
因此,您可以使用一些定义明确的行为来模拟接口:
//$upe = $this->getMockBuilder(\Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface::class)->getMock();
$upe = $this->getMockBuilder(\Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface::class)->getMock();
$upe->expects($this->any())
->method('encodePassword')
// omit following line,if you don't want to check for param
->with($this->equalTo('plainPassword'))
->willReturn('encodedPassword');
,然后将其提供给您的用户工厂:
$userfactory = new UserFactory($upe);
这在某种程度上取决于UserFactory的实现,希望它实际上是以指定的方式调用的,并且始终会返回相同的字符串。 (您可以更深入地模拟和/或自己实现接口以拥有更多控制权)