所以我有一个修改模型对象的服务方法
public function doSomething() {
$model = new Model();
// Modify the model with a bunch of private methods
return $model;
}
如果我想测试doSomething,我真的只有$ model可以使用。我可以在$ model上编写断言的唯一方法是使用它的公共接口。
$this->assertEquals($model->getName(), 'name');
让我感到困惑的是,我究竟在用这个断言测试什么?我测试getName是否正常工作还是我测试doSomething是否正常工作?
为了让我测试doSomething,我必须假设getName有效。那么如何确保是这种情况呢?
答案 0 :(得分:1)
您与doSomething()的合同是,它必须返回类型为" Model"的对象。您的合同不是getName()处理返回的对象。因此,测试$ model的类型是正确的:
$this->assertInstanceOf('Model', $model);
文档:PHPUnit -> assertInstanceOf()
作为一个提示," [i] deally,每个测试用例独立于其他测试用例" 2014-10-21 wikipedia.org/wiki/Unit_testing。
因此,在test_doSomethingTest *()中,您应该只测试该函数中发生的事情。检查返回类型,以及该功能发生的任何事情。测试getName()应该在它自己的test_getName *()。
中答案 1 :(得分:1)
根据您的代码,我会测试我返回了Model
的实例。然后使用公共访问器或assertAttributeEquals
检查对象的属性是否正确。这会测试模型的getter,但具有某些属性的对象是您期望发生的。
虽然你的类正在创建对象并修改它。我会改变方法以Model
作为参数。这样在我的测试中我可以创建一个mockModel
并确保使用正确的参数调用任何公共setter。这样做,我不必担心Model
对已设置属性的任何逻辑。
例如:
测试功能:
public function testDoSomething() {
$mockModel = $this->getMock('Model');
$mockModel->expects($this->once())
->method('foo')
->with('some argument');
$mockModel->expects($this->once())
->method('bar')
->with('some other argument');
$sut = new SUT();
$sut->doSomething($mockModel);
}
您的功能doSomething
只需要成为:
public function doSomething(Model $model) {
/** Do stuff with private methods **/
}
现在,您可以确保Model
的属性设置为正确的值,而不是取决于类中可能存在或不存在的逻辑。您还在帮助指定Model
需要填写的合同。您所依赖的任何新方法都将在您的集成/系统测试中出现。