Skip to content

Instantly share code, notes, and snippets.

@SelrahcD
Last active December 2, 2015 20:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SelrahcD/f479dd6d3edd385988fd to your computer and use it in GitHub Desktop.
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;
}
}

The problem is : What is the proper way to test discussion's method equals with PhpSpec.

@everzet
Copy link

everzet commented Dec 2, 2015

Replace "testing object methods" with "thinking about object behaviours". Which Discussion behaviour are you trying to achieve? Think out loud.

@SelrahcD
Copy link
Author

SelrahcD commented Dec 2, 2015

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 :)

@everzet
Copy link

everzet commented Dec 2, 2015

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.

@SelrahcD
Copy link
Author

SelrahcD commented Dec 2, 2015

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment