简短的问题: 有没有办法在SimpleTest中重置Mock对象,消除所有期望?
更长的解释:
我有一个我正在使用SimpleTest进行测试的类,并且它正在使用的Mock对象遇到一些问题。
该类是Logger
,并且记录器内部有许多Writer
个对象(FileWriter
,EmailWriter
等)。调用Logger::log()
方法在幕后执行一些逻辑并将消息路由到正确的编写器。写入器缓存在Logger类中以保存每次重新实例化。
在我的单元测试中,我设置了一个Logger,创建并添加了一些Mock Writer对象,然后使用像MockDBWriter->expectOnce()
这样的方法来测试Logger是否正常工作。
现在的问题是我想测试Logger的另一个功能,但expectOnce
预期仍然有效并导致我的后续测试失败。
function testWritesMessageOK() {
$log = Logger::getInstance();
$mock = new MockFileWriter($this);
$log->addWriter($mock);
$mock->expectOnce("write", "Message");
$log->write("Message"); // OK
}
// this is just an example - the actual test is much less inane
function testNumberOfWrites() {
$log = Logger::getInstance();
$mock = $log->getWriter();
$mock->expectCallCount('write', 2);
$log->write("One"); // fail - it doesn't match "Message"
$log->write("Two");
}
有没有办法重置Mock对象,删除所有期望?
答案 0 :(得分:2)
使用单独的模拟实例。
或者:
$mock = $log->getWriter();
$mock = new $mock;
或者:
$mock = new MockFileWriter($this);
// And then:
$mock = new MockDBWriter($this);
// And then:
$mock = new MockEmailWriter($this);
// etc.
我质疑缓存编写者保存重新实例化的智慧。如果你实例化是一个廉价的操作(即不创建数据库连接或任何东西)并推迟那种事情,直到你真正需要连接,如第一个查询,那么你将不需要缓存,这整个问题可能走开。
您可以做的另一件事是调用SimpleMock构造函数。
$mock = $log->getWriter();
$mock->SimpleMock();
这将完成所有这些:
/**
* Creates an empty action list and expectation list.
* All call counts are set to zero.
* @access public
*/
function SimpleMock() {
$this->_actions = &new SimpleCallSchedule();
$this->_expectations = &new SimpleCallSchedule();
$this->_call_counts = array();
$this->_expected_counts = array();
$this->_max_counts = array();
$this->_expected_args = array();
$this->_expected_args_at = array();
$test = &$this->_getCurrentTestCase();
$test->tell($this);
}
唯一的问题是tell()
最后调用会导致SimpleMock::atTestEnd()
在计算期望时被调用两次。但是,你可以解决这个问题:
// $this should == the test case in question
array_pop($this->_observers);
此答案基于SimpleTest 1.0.1版。