在 PHPUnit 中模拟接口时出现 TypeError

我有一个与以下相同的界面:


interface UserRepository

{

    public function save(User $user): User;

}

我需要为此函数编写一个单元测试


public function action()

{

    $data = $this->request->getParsedBody() ?? [];

    $user = new User($data);

    $this->userRepository->save($user);

}

我尝试模拟用户存储库界面


$app = $this->getAppInstance();

$container = $app->getContainer();

$user = new User(['a' => 'b']);

$userRepositoryProphecy = $this->prophesize(UserRepository::class);

$userRepositoryProphecy

    ->save($user)

    ->willReturn($user)

    ->shouldBeCalledOnce();

$container->set(UserRepository::class, $userRepositoryProphecy->reveal());

但返回


TypeError : Double\UserRepository\P1::save() 的返回值必须是 App\Domain\User\User 的实例,返回 null


我使用 slim-sketch 和 phpunit


慕森卡
浏览 144回答 1
1回答

慕斯709654

您的测试用例丢失,但我猜您在测试中保存的用户与您用于设置模拟的用户不同。为了澄清:    $userA = new User(['a' => 'b']);    $userB = new User(['c' => 'd']);    $prophecy = $this->prophesize(UserRepository::class);    $prophecy->save($userA)        ->willReturn($userA)        ->shouldBeCalledOnce();    $repo = $prophecy->reveal();    $repo->save($userA); // returns $userA    $repo->save($userB); // returns null如果您的用户存在您无法控制且不想消除的副作用,您可以使用回调来检查给定用户是否是您正在寻找的用户。    $prophecy->save(Argument::that(fn(User $user) => $user->data === ['a' => 'b']))        ->willReturnArgument()        ->shouldBeCalledOnce();
打开App,查看更多内容
随时随地看视频慕课网APP