我正在编写一些测试用例,并且我有一个使用Mock对象的测试用例。我需要检查是否从另一个类方法调用了两个类方法。这就是我所做的:
首先我制作了模拟:
Mock::generate('Parser');
然后,在我的测试中,我打电话给:
$P = new MockParser();
$P->expectOnce('loadUrl', array('http://url'));
$P->expectOnce('parse');
$P->fetchAndParse('http://url');
我的实现代码如下:
public function fetchAndParse($url) {
$this->loadUrl($url);
$this->parse();
}
loadUrl和parse()方法肯定存在。我在测试中遇到两次失败,都告诉我“[loadUrl]的预期通话数为[1]得到[0]”。我不知道发生了什么 - 从该函数调用方法!
谢谢,
杰米
答案 0 :(得分:4)
虽然我的经验是在.NET世界中使用模拟框架,但我认为你所做的不正确。
当要求为类创建模拟时,任何模拟框架都会为该类中的所有方法生成“存根”。这包括方法fetchAndParse。因此,当您在模拟对象$ P上调用fetchAndParse时,不会调用方法loadUrl和parse。你真正在做的是调用“stubbed”fetchAndParse方法。
我在PHP方面并不是很有经验,所以我不想尝试修复你的测试。希望其他人可以做到这一点。
答案 1 :(得分:1)
你误解了嘲讽是如何运作的。如果使用依赖注入在类中设置辅助对象,则可以模拟注入的对象。之后,您可以模拟原始对象的行为(界面)。更好的方法是模拟接口,因为您可以在不创建任何实现当前接口的类的情况下进行开发。
以你的例子:
interface UrlLoaderInterface {
public function load($url);
}
class YourParser {
protected $urlLoader;
protected $source;
public function setUrlLoader(UrlLoaderInterface $urlLoader) {
$this->urlLoader = $urlLoader;
}
public function fetchAndParse($url) {
$this->loadUrl($url);
$this->parse();
}
public function loadUrl($url) {
$this->source = $this->urlLoader->load($url);
}
public function parse() {
}
}
Mock::generate('UrlLoaderInterface', 'MockUrlLoader');
class TestYourParser extends UnitTestCase {
public function testShouldCallUrlLoaderByFetchAndParse() {
$testUrl = 'http://url';
$urlLoader = new MockUrlLoader();
$urlLoader->expectOnce('load', array($testUrl));
$urlLoader->returns('load', 'source', array($testUrl));
$parser = new YourParser();
$parser->setUrlLoader($urlLoader);
$parser->fetchAndParse($testUrl);
}
}
顺便说一下。你的例子是失败的,因为方法名称不能包含像'和','或','if'等字样......一个方法只允许做一件事。如果您使用这些单词,那么您可以确定您的代码设计错误。