1

I'm making tests for an web application, it removes a Likes Record from database, but I'm getting this ambiguous fail.

Expectation failed for method name is equal to when invoked 1 time(s). Parameter 0 for invocation myMelomanBundle\Repository\LikesRepository::remove('myDomain\Entity\Likes') does not match expected value. Failed asserting that 'myDomain\Entity\Likes' is an instance of class "myDomain\Entity\Likes".

DislikePublicationUseCaseTest.php

    <?php

    namespace myMelomanBundle\Likes;


    class DislikePublicationUseCaseTest extends \PHPUnit_Framework_TestCase
    {
    const User = 2;
    const PUB = 15;
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $publicationRepositoryMock;
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $userRepositoryMock;
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $likesRepositoryMock;
    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $entityManagerMock;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $userMock;

    /**
     * @var \PHPUnit_Framework_MockObject_MockObject
     */
    private $publicationMock;

    private $likesMock;

    /**
     * @var DislikePublicationUseCase
     */
    private $dislikePublicationUseCase;

    /**
     * @var LikeDTO
     */
    private $likeDTO;

    protected function setUp()
    {
        $this->publicationRepositoryMock = $this-
>createMock(PublicationRepository::class);
        $this->userRepositoryMock = $this-
>createMock(UserRepository::class);
        $this->likesRepositoryMock = $this-
>createMock(LikesRepository::class);
        $this->entityManagerMock = $this-
>createMock(EntityManager::class);
        $this->userMock = $this->createMock(User::class);
        $this->publicationMock = $this->createMock(Publication::class);
        $this->likesMock = $this->createMock(Likes::class);
        $this->likeDTO = new LikeDTO(self::User, self::PUB);
        $this->dislikePublicationUseCase = new DislikePublicationUseCase(
            $this->publicationRepositoryMock,
            $this->userRepositoryMock,
            $this->likesRepositoryMock,
            $this->entityManagerMock
        );
    }

    protected function tearDown()
    {
        $this->publicationRepositoryMock = null;
        $this->userRepositoryMock = null;
        $this->likesRepositoryMock = null;
        $this->entityManagerMock = null;
        $this->userMock = null;
        $this->publicationMock = null;
        $this->likesMock = null;
    }

    /** @test */
    public function dummyTest()
    {
        $this->dislikePublicationUseCase;
    }

    /** @test */
    public function shouldRemoveALikeOneTimeIfItExist()
    {
        $this->givenALikeRepositoryThatHasASpecificLike();
        $this->andGivenAUserRepositoryThatHaveASpecifiUser();
        $this->andGivenAPublicationRepositoryThatHaveASpecificPublication();
        $this->thenTheLikeShouldBeRemovedOnce();
        $this->whenTheDislikePublicationUseCaseIsExecutedWithASpecificParameters();
    }

    private function givenALikeRepositoryThatHasASpecificLike()
    {
        $this->likesRepositoryMock
            ->method('findOneBy')
            ->willReturn(Likes::class);
    }
    private function andGivenAUserRepositoryThatHaveASpecifiUser()
    {
        $this->userRepositoryMock
            ->method('find')
            ->willReturn($this->userMock);
    }

    private function andGivenAPublicationRepositoryThatHaveASpecificPublication()
    {
        $this->publicationRepositoryMock
            ->method('find')
            ->willReturn($this->publicationMock);
    }

    private function thenTheLikeShouldBeRemovedOnce()
    {
        $this->likesRepositoryMock
            ->expects($this->once())
            ->method('remove')
            ->with($this->isInstanceOf(Likes::class)); // Here Fails
    }

    private function 
    whenTheDislikePublicationUseCaseIsExecutedWithASpecificParameters()
    {
        $this->dislikePublicationUseCase->execute($this->likeDTO);
    }
}

DislikePublicationUseCase.php

 <?php

namespace myDomain\UseCases\Like;

class DislikePublicationUseCase
{
    private $publicationRepository;
    private $userRepository;
    private $likesRepository;
    private $entityManager;

    public function __construct (
        PublicationRepositoryInterface $publicationRepository,
        UserRepositoryInterface $userRepository,
        LikesRepositoryInterface $likesRepository,
        EntityManagerInterface $entityManager
    )
    {
        $this->publicationRepository    = $publicationRepository;
        $this->userRepository           = $userRepository;
        $this->likesRepository          = $likesRepository;
        $this->entityManager            = $entityManager;
    }

    public function execute(LikeDTO $likeDTO)
    {
        try {

            $user           = $this->userRepository->find($likeDTO->getUserId());
            $publication    = $this->publicationRepository->find($likeDTO->getPublicationId());

            $like = $this->likesRepository->findOneBy(
                array(
                    'user' => $user,
                    'publication' => $publication
                )
            );
            $this->likesRepository->remove($like);

            return true;

        } catch (\Exception $e) {
            return false;
        }
    }
}

Why it fails if it's the same entity? It's the entity that I'm expecting.

3 Answers 3

2

Look closely at this method:

private function givenALikeRepositoryThatHasASpecificLike()
{
    $this->likesRepositoryMock
        ->method('findOneBy')
        ->willReturn(Likes::class);
}

Spotted it yet?

Spoiler:

->willReturn(Likes::class);

The mock will return the string Likes::class.

var_dump(Likes::class); // string(19) "myDomain\Entity\Likes"

Change it to something like:

private function givenALikeRepositoryThatHasASpecificLike()
{
    $this->likesRepositoryMock
        ->method('findOneBy')
        ->willReturn(new Likes());
}
Sign up to request clarification or add additional context in comments.

Comments

1

It seems like you want to pass an instance of Likes as a parameter to LikesRepository::remove(). You're close, but you're trying to pass a boolean as a parameter instead.

So you need to pass it a Likes instance. You already have a mock of it, so pass it:

private function thenTheLikeShouldBeRemovedOnce()
{
    $this->likesRepositoryMock
        ->expects($this->once())
        ->method('remove')
        ->with($this->likesMock); // Here Fails
}

I don't know what remove()'s return value is, but you can test that too:

private function thenTheLikeShouldBeRemovedOnce()
{
    $this->likesRepositoryMock
        ->expects($this->once())
        ->method('remove')
        ->with($this->likesMock)
        ->will($this->returnValue(true)); // if remove() returns true on success
}

1 Comment

thanks a lot @ishegg! I was focusing on on the wrong method! Now it works! Thanks a lot :)
1

$this->assertInstanceOf(Likes::class, $likes); accepted two argument class and object to asserts if instance of class expected object. And, you can use callback function to asserts parameters passed to methods

6 Comments

First I was tried with no luck. Second does not work...Thanks
what is the error, if you use correctly $this->assertInstanceOf ?
Like this...->with($this->assertInstanceOf(Likes::class, $this->likesMock)); "Failed asserting that 'myDomain\Entity\Likes' matches expected null." Regards
try this ->with($this->callback( function ($like) { $this->assertInstanceOf(Likes::class, $like); }));
Same as the first one: Failed asserting that 'myDomain\Entity\Likes' is an instance of class "myDomain\Entity\Likes".
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.