Open stof opened 10 years ago
I don't think so. But we could introduce compound predictions, like we have compound argument tokens: https://github.com/phpspec/prophecy/blob/master/spec/Prophecy/Argument/Token/LogicalAndTokenSpec.php
I sometimes find the need for multiple predictions. Consider a case like:
// simple value object
class Entity {
private $name;
public function __construct($name) { $this->name = $name; }
public function getName() { return $this->name; }
}
// system under test
// creates value object(s), sends them to collaborator
class Manager
{
public function doStuff()
{
$entity1 = new Entity('first');
$entity2 = new Entity('second');
$this->collab->perform($entity1);
$this->collab->perform($entity2);
}
public function __construct(Collaborator $collab) { $this->collab = $collab; }
}
To spec the doStuff
method I intuitively wrote a test like
function it_does_stuff_with_collaborator(Collaborator $collab)
{
$collab->perform(Argument::which('getName', 'first'))->shouldBeCalled();
$collab->perform(Argument::which('getName', 'second'))->shouldBeCalled();
$this->doStuff();
}
which does not work.
Using a callback style argument matcher did not get me further for the same reason I guess?
function it_does_stuff_with_collaborator(Collaborator $collab)
{
$collab->perform(Argument::that(function ($entity) {
return $entity->name === 'first';
}))->shouldBeCalled();
$collab->perform(Argument::that(function ($entity) {
return $entity->name === 'second';
}))->shouldBeCalled();
$this->doStuff();
}
What do you mean checking predictions immediately @stof? Or does that pain point out an obvious flaw in my system under test? Even getting the entity from a factory type collaborator would not help if both calls to perform
would act on the same instance.
@hanneskaeufler your use case can be achieved if you use a spy to check predictions after the action (checking them immediately when you ask for them) instead of using a mock in which predictions are registered to be checked at the end of the test:
function it_does_stuff_with_collaborator(Collaborator $collab)
{
$this->doStuff();
$collab->perform(Argument::which('getName', 'first'))->shouldHaveBeenCalled();
$collab->perform(Argument::which('getName', 'second'))->shouldHaveBeenCalled();
}
Hi @stof ,
Did you know if this feature request will be implemented soon?
I'm on a similar situation where I need to check consecutive calls in a method and check if the arguments passed are those I expect:
$collab->perform(
Argument::that(
function(MyEntity $entity) {
$this->assertSame('expectedvalue', $entity->getName());
return true;
}
)
)->shouldBeCalled();
$collab->perform(
Argument::that(
function(MyEntity $entity) {
$this->assertSame('anotherExpectedValue', $entity->getName());
return true;
}
)
)->shouldBeCalled();
I'm trying to do the same logic as the PhpUnit mock has about consecutive calls.
Do you know if there's another way to do it?
Thanks a lot!
@xserrat no idea. this will be implemented when someone works on it. And I'm not working on it.
@stof Thank you so much for your fast reply! I'll note that to try to implement it and open a pull request :)
+1 - would be great to see.
Currently, a MethodProphecy can only have a single delayed prediction (registered with
should()
and checked when the prophet checks predictions). Setting a new prediction will loose the previous one. To test multiple predictions, it is necessary to check them immediately withshouldHave()
.Could it make sense to register multiple predictions on the same prophecy ?