Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 关于god对象、测试类型、测试覆盖率以及如何使类单元可测试的说明_Php_Unit Testing_Testing_Domain Driven Design_Functional Testing - Fatal编程技术网

Php 关于god对象、测试类型、测试覆盖率以及如何使类单元可测试的说明

Php 关于god对象、测试类型、测试覆盖率以及如何使类单元可测试的说明,php,unit-testing,testing,domain-driven-design,functional-testing,Php,Unit Testing,Testing,Domain Driven Design,Functional Testing,我目前试图做的是在单元测试中测试类的构造函数 我不确定这个对象的实例是否是“上帝对象”,我会说它不是,因为它只聚合了几个其他组件 不管怎样,我愿意接受更好的设计 粗略的类图如下所示 World是可疑的神类。它的依赖项,ServiceProvider、CommandRegistry、EventHub和Environment通过其构造函数注入 在其构造函数中,World执行以下操作: 将其依赖项存储在私有字段中 向eventHub注册一个hook($this,'onCommandIssued'),

我目前试图做的是在单元测试中测试类的构造函数

我不确定这个对象的实例是否是“上帝对象”,我会说它不是,因为它只聚合了几个其他组件

不管怎样,我愿意接受更好的设计

粗略的类图如下所示

World
是可疑的神类。它的依赖项,
ServiceProvider
CommandRegistry
EventHub
Environment
通过其构造函数注入

在其构造函数中,
World
执行以下操作:

  • 将其依赖项存储在私有字段中
  • eventHub
    注册一个hook
    ($this,'onCommandIssued')
    ,以便
    world
    接收有关所有命令的通知,这些命令不是通过
    world
    实例本身执行的(
    world
    还有一个方法
    executeCommand
  • 告诉环境采用世界:
    $this->environment->adoptWorld($this)
    。环境的作用是使世界适应运行环境的某些实际情况,例如,web环境具有一些在控制台应用程序环境中不可用的特定服务(例如“会话”服务)
  • 通过事件中心通知世界的构建已完成:
    $this->eventHub->notify(newworldconstructedevent($this))
  • 也许这看起来像一个沉重的构造器,但它只是被定义为“构建世界”

    World
    基本上是发送命令(作为数据传输对象,通过
    World::executeCommand()
    )的网关,不同的服务可以向其注册钩子

    现在谈谈问题:

  • 我试图对这个构造函数进行单元测试,但我必须添加一堆
    @用法
    注释,这让它感觉像是单元测试以外的任何东西。那是什么,功能测试?单元测试
    World
    很尴尬,测试其他任何东西都是非常琐碎的,我没有看到这个问题出现在任何其他测试中,这让我问自己为什么会这样,以及如何改进设计
  • World
    是神的对象吗?它所做的只是聚合其他组件并将调用转发给它们
  • 如何正确地对
    World
    的方法进行单元测试?如果我使用了很多存根,并且注入了依赖项,这仍然是单元测试吗
  • 这是针对一个领域驱动的设计(复杂)应用程序,我愿意接受一些建议,这些建议将使设计更好(可测试和解耦)

    如果您需要更多详细信息,请在评论中告诉我


    由于我不知道这场讨论将导致什么,我可能会改进我的问题。

    我最终通过设置适当的期望值和模拟依赖项来对类进行单元测试:

    <?php
    
    namespace Common\World;
    
    use TestFramework\TestCase;
    
    class WorldTest extends TestCase
    {
        /**
         * @test
         * @covers \Common\World\World::__construct
         * @uses   \Common\World\World::setEventHub
         * @uses   \Common\World\Event\Adopted
         */
        public function construction()
        {
            /** @var \Common\World\Environment $environmentStub |\PHPUnit_Framework_MockObject_MockObject */
            $environmentStub = $this->getMockBuilder('Common\World\Environment')->getMock();
            /** @var \Common\World\EventHub|\PHPUnit_Framework_MockObject_MockObject $eventHubStub */
            $eventHubStub = $this->getMock('Common\World\EventHub');
    
            $environmentStub->expects($this->once())
                ->method('adoptWorld')
                ->will($this->returnCallback(function (World $world) use ($eventHubStub) {
                    $world->setEventHub($eventHubStub);
                    return true;
                }));
            $eventHubStub->expects($this->once())
                ->method('trigger')
                ->with($this->isInstanceOf('Common\World\Event\Adopted'));
            $this->assertInstanceOf('Common\World\World', new World($environmentStub));
        }
    
        /**
         * @test
         * @covers \Common\World\World::__construct
         * @expectedException \RuntimeException
         * @expectedExceptionMessage the environment has rejected this world for incompatibility reasons
         */
        public function construction_rejected()
        {
            /** @var \Common\World\Environment $environmentStub */
            $environmentStub = $this->getMockBuilder('Common\World\Environment')->getMock();
            $environmentStub->expects($this->once())
                ->method('adoptWorld')
                ->will($this->returnValue(false));
    
            new World($environmentStub);
        }
    
    
    }
    

    我认为您应该提供一个mock EventHub,并检查是否调用了hook方法。根据需要对其他依赖项重复此操作。我怀疑我在你的问题中遗漏了什么。你是说存根
    EventHub
    ,对吗?测试的类是
    World
    ,因此这将是我的示例中唯一的模拟。无论如何,谢谢,这是一个好主意。模拟和存根不一样:。为了测试您的构造函数,我们关心的只是使用预期参数调用EventHub和Environment方法。作为一名模拟测试人员(使用Fowler的术语),我会模拟依赖项。您可能更像是一个经典的测试人员。AFAIK mock是测试断言的对象,而存根是您注入到SUT中的“mock”,SUT依赖于它(“la依赖注入”)。