While refactoring my code base I found a piece of code which I’d like to extract into a separate class.
It will serve thumbnails for user profile pictures. The class (let’s name it UserImageManager) will hold an instance of UserMapper and an instance of ImageRenderer.
Now I do have a method for retrieving the cached url for a users profile picture. This method retrieves a User object from the UserMapper and triggers the render method of ImageRenderer with the image path stored in the User object.
I wrote a test for this tiny function, mocking out the ImageRenderer and now I do not have a single assertion in this test case. It would not make any sense to assert the return value of the function, because it returns the cache file path, which is returned by the mocked ImageRenderer.
Now my question is: is it still a valid unit test, even with no assertions? Or how should I rewrite my test, not only checking calls to mock objects?
// The unit test
public function renderImageWillReturnCacheImagePath() {
$this->_userImageManager->setImage(
// Returns the ImageRenderer mock
$this->_getImageMock(BASE_PATH . 'uploads/2012-06-06-wegmeister-91792.png', false, false)
);
// Invokes the function
$image = $this->_userImageManager->render('wegmeister');
}
// The method to be tested
public function render($username, $width = false, $height = false) {
$user = $this->_userMapper->getUserByUsername($username);
if($user !== false && trim($user->getImage()) !== '') {
$srcImage = $this->_folderUserImages . $user->getImage();
}
else {
$srcImage = $this->_placeholderUserImage;
}
$dstImage = $this->_image->render($srcImage, 'jpg', $width, $height);
if ($dstImage === false || empty($dstImage)) {
throw new UnexpectedValueException('ImageRenderingFailed');
}
return $dstImage;
}
A test with no assertion is an incomplete test.
If you can’t imagine what and how to assert, I’d say it means that the outcome of the method (unit) you want to test is undefined.
As you have not shown any specification nor told which type that function returns, the only thing I could imagine that you can test is if the exeception is thrown when needed.
Additionally it looks like that that method does too much and is too complex. So I would invest the time not in creating tests but to refactor the classes.
In the future you should write tests before you write the code, so you don’t come into this situation.