Mocking same method with different "with" and different "return" throw an exception
| Q | A |
|---|---|
| PHPUnit version | 9.2.6 |
| PHP version | 7.4.8 |
| Installation Method | Composer |
Summary
Mocking same method with different "with" and different "return"
Current behavior
Expectation failed for method name is "getRepository" when invoked zero or more times
Parameter 0 for invocation Doctrine\ORM\EntityManager::getRepository('Op\AppBundle\Entity\Order') does not match expected value.
Failed asserting that two strings are equal.
Expected :'Op\AppBundle\Entity\Customer'
Actual :'Op\AppBundle\Entity\Order'
How to reproduce
$this->em
->method('getRepository')
->with(Customer::class)
->willReturn($this->customerRepository);
$this->em
->method('getRepository')
->with(Order::class)
->willReturn($this->orderRepository);
$this->em->getRepository(Order::class)->findOneByOrderId($id);

Expected behavior
If "matcher" did not throw an exception on the second "match" (invoke), we should not throw an exception
Thank you for your report.
Please provide a minimal, self-contained, reproducing test case that shows the problem you are reporting.
Without such a minimal, self-contained, reproducing test case I will not be able to investigate this issue.
@sebastianbergmann , I have sucessfully reproduced the issue (PHPUnit 9.6.3 by Sebastian Bergmann and contributors.) To reproduce you can use TestCase and mock the doctrine's entity manager, have the entity manager match the getRepository method with two repository classes consecutively (order does not matter); you will see the matcher exception. Example:
// doctrine entities
class Order {}
class Customer {}
// doctrine repositories
class OrderRepository {}
class CustomerRepository {}
// Test Subject
class Order {
public function __construct(EntityManagerInterface $em) {
$order = $this->$em->getRepository(OrderRepository::class)->findBy(['id' => 1]);
}
}
class OrderTest extends TestCase
{
protected function setUp(): void {
$this->em = $this->createMock(EntityManagerInterface::class);
$this->customerRepositoryMock = $this->createMock(CustomerRepository::class);
$this->orderRepositoryMock = $this->createMock(OrderRepository::class);
$this->em->method('getRepository')->with(Customer::class)
->willReturn($this->customerRepositoryMock);
$this->em->method('getRepository')->with(Order::class)
->willReturn($this->orderRepositoryMock);
}
}
// Then try test a class that uses these mock and try to get anything from these repositories,
// it will throw.
// I hope I could make it reproducible for you.
Thank you for your report.
Please provide a minimal, self-contained, reproducing test case that shows the problem you are reporting.
Without such a minimal, self-contained, reproducing test case I will not be able to investigate this issue.
Lol. It's been 2y+, somehow I've missed this notification. It's irrelevant for me atm. 💪👍
Sorry, but something that uses Doctrine's entity manager is neither minimal nor self-contained.