Unit testing 黑盒还是白盒单元测试?
假设我有这样的代码:Unit testing 黑盒还是白盒单元测试?,unit-testing,Unit Testing,假设我有这样的代码: class SomeEntity { // ... some properties and methods here public function saveAndChangeState() { $result = $this->save(); // method for saving object somehow $this->changeState(); // changes state of ob
class SomeEntity
{
// ... some properties and methods here
public function saveAndChangeState()
{
$result = $this->save(); // method for saving object somehow
$this->changeState(); // changes state of object - e.g., sets some properties e.t.c.
return $result;
}
public function save() { /* ... */ }
public function changeState() { /* ... */ }
}
我可以为这个方法编写两种单元测试
白盒:
class SomeEntityTest extends TestCase
{
public function testSaveAndChangeState()
{
$expected = true;
$SomeEntity = $this->getMock('SomeEntity', [
// replace only these methods
'save',
'changeState',
]);
$SomeEntity->expects($this->once()) // should be called once
->method('save')
->willReturn($expected); // stub implementation will return $expected
$SomeEntity->expects($this->once())
->method('changeState');
$actual = $SomeEntity->saveAndChangeState();
$this->assertEquals($expected, $actual);
}
}
和黑盒:
class SomeEntityTest extends TestCase
{
public function testSaveAndChangeState()
{
$SomeEntity = new SomeEntity();
$result = $SomeEntity->saveAndChangeState();
// here come assertions about state - that I can see a persisted object,
// some properties of $SomeEntity have changed e.t.c.
}
}
如果我选择whitebox:
将更短testSaveAndChangeState()
如果我不适当地更改testSaveAndChangeState()
的实现,则不会失败-因此我的单元测试不会提醒我changeState()
工作不正确saveAndChangeState()
class SomeEntityTest extends TestCase
{
public function testSaveAndChangeState()
{
$SomeEntity = new SomeEntity();
$result = $SomeEntity->saveAndChangeState();
// here come assertions about state - that I can see a persisted object,
// some properties of $SomeEntity have changed e.t.c.
}
}
将更加困难,因为我需要检查应用程序中被testSaveAndChangeState()
和save()
changeState()触及的每个部分
如果我不适当地更改testSaveAndChangeState()
的实现,将提醒我有关changeState()
saveAndChangeState()的问题
- 我将有大量的代码重复-因为在
中,我将主要重复testSaveAndChangeState()
和save()
changeState()测试中的断言
我的问题是-我应该选择什么?您应该使用whitebox,并为save()和changeState()添加测试。
我过去认为blackbox是一种可行的方法,但现在我使用whitebox,因为当我更改代码而测试失败时,测试向我展示了使用的方法是如何工作的,并帮助我记住所有需要考虑的情况。最佳实践是分离业务关注点并测试对象之间的交互 将域对象(实体)与域交互者(实体服务)分离,并将域交互者与外部关注点(如数据持久性(数据库))分离 然后可以针对模拟对象进行黑盒测试,并确保EntityService正确调用数据持久层 如果您保持代码高度耦合,并将业务逻辑与检索/持久性/验证/其他关注点相结合,那么测试您的系统非常困难,很难发现bug,也很难更改 样本单元测试伪码
[TestMethod]
public void MyEntityService_SaveEntity_DataAccessSaveIsCalled()
{
var inMemoryDatabase = new FakeDatabase();
var service = new MyEntityService(inMemoryDatabase);
var sampleEntity = new MyEntity { Name = "sampleObject" };
service.Add(sampleEntity);
Assert.IsTrue(inMemoryDatabase.LastSavedEntity == sampleEntity);
}