php - 如何测试工厂类?

标签 php unit-testing design-patterns testing

给定这个类:

class MyBuilder {
    public function build($param1, $param2) {

        // build dependencies ...

        return new MyClass($dep1, $dep2, $dep3);
    }
}

如何对这个类进行单元测试?

单元测试意味着我想测试它的行为,所以我想测试它是否用正确的依赖关系构建了我的对象。但是,new 指令是硬编码的,我无法模拟它。

现在,我已经添加了类名作为参数(这样我就可以提供模拟类的类名),但它很难看:

class MyBuilder {
    public function build($classname, $param1, $param2) {

        // build dependencies ...

        return new $classname($dep1, $dep2, $dep3);
    }
}

是否有干净的解决方案或设计模式使我的工厂可测试?

最佳答案

工厂本质上是可测试的,您只是试图对实现进行过于严格的控制。

您将检查您是否通过 $this->assertInstanceOf() 获得了您的类的实例。然后使用生成的对象,您将确保正确设置属性。为此,您可以使用任何公共(public)访问器方法或使用 PHPUnit 中可用的 $this->assertAttribute* 方法。

http://phpunit.de/manual/current/en/writing-tests-for-phpunit.html#writing-tests-for-phpunit.assertions.assertEquals

许多常见断言还能够检查 protected 属性和私有(private)属性的属性。

我不会在你的参数列表中指定类名,因为你的用法是工厂将只返回一种类型,而且只有依赖项被改变了。让它返回模拟对象类型是不必要的,并且会使您的测试更加复杂。

测试最终看起来像这样:

public function testBuild() {
    $factory = new MyBuilder();

    //I would likely put the following into a data provider
    $param1 = 'foo';
    $param2 = 'bar';

    $depen1 = 'boo';
    $depen2 = 'baz';
    $depen3 = 'boz';

    $object = $factory->build($param1, $param2);

    $this->assertInstanceOf('MyClass', $object);

    //Check the object definition
    //This would change depending on your actual implementation of your class
    $this->assertAttributeEquals($depen1, 'attr1', $object);
    $this->assertAttributeEquals($depen2, 'attr2', $object);
    $this->assertAttributeEquals($depen3, 'attr3', $object);
}

您现在要确保您的工厂返回一个正确的对象。首先确保它是正确的类型。然后确保它已正确初始化。

您依赖于 MyClass 的存在来使测试通过,但这并不是一件坏事。您的工厂旨在创建 MyClass 对象,因此如果该类未定义,那么您的测试肯定会失败。

在开发过程中测试失败也不是坏事。

关于php - 如何测试工厂类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20302156/

相关文章:

linux - grep linux 中的模式(重复/出现超过 n)

php - PHP 和 SQL 是否足以统计页面浏览量和下载量?

php - Xpath 查询包含

php - 将具有多个字段的数组传递给 codeigniter 中的 View

unit-testing - 如何验证是否调用了Microsoft伪造品(beta) stub /填充程序(如Rhino Mocks中的AssertWasCalled)?

html - 提供仅用于测试目的的 html 元素 id 属性是一种好习惯吗?

c# - C# 中 ValidationError 类的合理模式

php - Python加速器

python - 如何在 Python 中模拟具有嵌套属性的对象?

python - 修复 "IFs hell"的最佳方法是什么?