The problem is : What is the proper way to test discussion's method equals with PhpSpec.
-
-
Save SelrahcD/f479dd6d3edd385988fd to your computer and use it in GitHub Desktop.
<?php | |
class Discussion | |
{ | |
private $id; | |
private function __construct(DiscussionId $discussionId) | |
{ | |
$this->id = $discussionId; | |
} | |
public function equals(Discussion $discussion) | |
{ | |
return $this->id->equals($discussion->id); | |
} | |
} | |
<?php | |
class DiscussionId | |
{ | |
private $id; | |
public function __construct($d) | |
{ | |
$this->id = $id; | |
} | |
public function equals(DiscussionId $discussionId) | |
{ | |
return $this->id === $discussionId->id; | |
} | |
} |
I want a discussion to be equal to a Discussion with the same DiscussionId.
We tried something like this :
function it_is_equal_to_a_discussion_with_same_DiscussionId()
{
$discussionId = new DiscussionId(1);
$this->beConstructedWith($discussionId);
$anotherDiscussion = new Discussion($discussionId);
$this->equals($anotherDiscussion)->shouldReturn(true);
}
function it_is_not_equal_to_a_discussion_with_another_DiscussionId()
{
$discussionId = new DiscussionId(1);
$this->beConstructedWith($discussionId);
$anotherDiscussion = new Discussion(new DiscussionId(2));
$this->equals($anotherDiscussion)->shouldReturn(false);
}
The thing which was bothering us was that we weren't testing that the logic was delegated to DiscussionId's equals method. Is it for better or for worst I'm not sure. I would say really trying to ensure DiscussionId's equals is called leads to make the implementation and the code tight...
Another (small) issue is that constructing discussions could become tedious if several arguments are added to constructor but I guess we could inject dummies.
I don't know if I'm right about all this. What do you think ?
Anyway, thanks for your time & answers :)
You ended up with 2 very good examples in my book 👍
The thing which was bothering us was that we weren't testing that the logic was delegated to DiscussionId's equals method.
I generally am not interested in communication between two values, I am interested in communication between two roles. In your case, you don't have a role - you have a very specific value representation - DiscussionId
. DiscussionId
is not a collaborator, it is a value (an object incorporating a singular value with a set of behaviour surrounding it). I wouldn't stub or mock DiscussionId
as I wouldn't stub or mock array or collection - there's no collaboration with ValueObject's, you just use them as you would use integers or strings in your tests.
I didn't think of a value object as a value instead of a collaborator but yes it makes sens. (Didn't see the big V before object, duh...)
I'm curious, what are the two examples ?
I guess clarifying that a VO is a value as native value would be is one of them but I can't figure what the second would be.
Replace "testing object methods" with "thinking about object behaviours". Which
Discussion
behaviour are you trying to achieve? Think out loud.