Symfony的2.8.13 /學說ORM 2.5.5/5.7.5的PHPUnit的Symfony2:學說:PHPUnit的:在單位嘲笑實體管理器在沖洗時設置實體ID測試
我想測試一個類的方法利用了學說實體經理。這個公共方法調用一個私有實例化一個Bookmark實體,刷新它並返回這個實體。然後,在測試的方法中,我需要訪問實體Id。除了書籤實體本身以外,一切都是嘲弄的。主要的問題是我的實體中沒有setId()方法。這裏是代碼和我的主要想法來解決這個問題,但我不知道它是否正確?
測試的類和方法
class BookmarkManager
{
//...
public function __construct(TokenStorageInterface $tokenStorage, ObjectManager $em, Session $session)
{
//...
}
public function manage($bookmarkAction, $bookmarkId, $bookmarkEntity, $bookmarkEntityId)
{
//...
$bookmark = $this->add($bookmarkEntity, $bookmarkEntityId);
//...
$bookmarkId = $bookmark->getId();
//...
}
private function add($entity, $entityId)
{
//...
$bookmark = new Bookmark();
//...
$this->em->persist($bookmark);
$this->em->flush();
return $bookmark;
}
}
測試
class BookmarkManagerTest extends \PHPUnit_Framework_TestCase
{
public function testThatRestaurantAdditionToBookmarksIsWellManaged()
{
//...
// THIS WON'T WORK AS NO setId() METHOD EXISTS
$entityManagerMock->expects($this->once())
->method('persist')
->will($this->returnCallback(function ($bookmark) {
if ($bookmark instanceof Bookmark) {
$bookmark->setId(1);
}
}));
//...
$bookManager = new BookmarkManager($tokenStorageMock, $entityManagerMock, $sessionMock);
//...
}
}
解決方案?反射類
1-製作使用所提出here:
$entityManagerMock->expects($this->once())
->method('persist')
->will($this->returnCallback(function ($bookmark) {
if ($bookmark instanceof Bookmark) {
$class = new \ReflectionClass($bookmark);
$property = $class->getProperty('id');
$property->setAccessible(true);
$property->setValue($bookmark, 1);
//$bookmark->setId(1);
}
}));
2-創建從真實一個延伸的測試Boookmark實體並添加SETID()方法。然後創建這個類的模擬,並用這個替換和定製從ReturnCallback方法得到的一個?這似乎蹩腳...
有什麼想法?謝謝你的幫助。
我知道反射應該是邪惡的,但我認爲你提到的反射方法是最好的選擇。對於創建僅用於測試的類而言,感覺不對,例如TestBookmark或MockEntityManager。如果你打算在測試中定期做這些事情,我發現創建一個只有'setProperty($ object,$ property,$ value)'方法的ReflectionSetterTrait纔有用。 – mickadoo
@mickadoo我同意,這個特質是一個不錯的選擇。對於實體經理我不創建一個特定的類,我只是用PHPUnit模擬構建器嘲笑它。無論如何,反思似乎是這種情況下的解決方案。 – Cruz