I'm using a repository pattern design and I've hit a stumbling block when writing a unit test for one of my methods. I'm fairly new to writing unit tests, so I would appreciate any help!
Let's say I have a method which creates a product and uses setters to set the data.
public function addProduct(array $data)
{
$new = $this->repository->make(); // returns new Product object
$new->setTitle($data['title']);
$new->setPrice($data['price']);
$new->setImage($data['image']);
$new->setStock($data['stock']);
return $this->repository->save($new); // returns bool
}
Now when I'm writing unit tests for this method, what should I actually be testing?
- Should I just check the return type and leave it at that?
- Should I mock the return of
make()
and ensure that all the setters were run? - Should I mock just the
repository
and ensure thatmake()
andsave()
were run?
Initially, I decided to go with all three options. However, my concern came from when I started option 2, writing tests to ensure that all the setters were run
Should the unit test really be concerned about whether all the setters ran? What happens if I add more fields? It seems like doing this would mean the tiniest change could result in the unit test failing when the method actually does as performed.
This is how I've wrote my unit test so far, but I'm really unsure about how strict it is
public function testAddProductAddsProductWithCorrectAttributes()
{
$newMock = Mockery::make(ProductInterface::class)
->shouldReceive('setTitle')
->withArgs(['Test title'])
->shouldReceive('setPrice')
->withArgs([10.99])
->shouldReceive('setImage')
->withArgs(['/foobar.jpg'])
->shouldReceive('setStock')
->withArgs(['In Stock']);
$repoMock = Mockery::make(RepositoryInterface::class)
->shouldReceive('make')
->andReturn($newMock)
->shouldReceive('save')
->withArgs([$newMock])
->andReturn(true);
$service = new Service($repoMock);
$add = $service->addProduct([
'title' => 'Test title',
'price' => 10.99,
'image' => '/foobar.jpg',
'stock' => 'In Stock'
]);
$this->assertTrue($add);
}