【问题标题】:A method Bar in class Foo logs a message with debug method. How to write testcode for method Bar类 Foo 中的方法 Bar 使用调试方法记录消息。如何为方法 Bar 编写测试代码
【发布时间】:2019-09-23 16:11:10
【问题描述】:

我的类 Foo 有一个名为 Bar 的方法,当调用它时会记录一条调试消息。 Foo 类在其 __contruct 方法中获取 \Psr\Log\LoggerInterface $logger。我在我的 FooTest 类中创建了一个 testBar 方法,但是我的 Bar 方法中的调试方法给出了以下错误

PHP 致命错误:类 Mock_LoggerInterface_a49cf619 包含 8 个抽象 > 方法,因此必须声明为抽象或实现其余 > 方法(Psr\Log\LoggerInterface::emergency, Psr\Log>\LoggerInterface::alert, Psr\Log\ /var/www/html/myproject/vendor/phpunit/phpunit-mock-objects>/src/Generator.php(264) 中的 LoggerInterface::critical, ...) :第 1 行的 eval() 代码

我的课程代码如下

use Psr\Log\LoggerInterface;

class Foo {


    private $logger;
    private $myclassObject;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
    public function Bar ()
    {
      // some code
      $logger->debug ('debug message')

    }
}

下面给出我的测试类

use PHPUnit\Framework\TestCase;

class FooTest extends TestCase
{

    private $logger;
    public function setUp()
    {
        $this->logger = $this->getMockBuilder('\Psr\Log\LoggerInterface')
            ->setMethods(null)
            ->getMock();

        $this->logger->expects($this->any())
            ->method('debug')
            ->willReturn('Message Logged');
    }

    $this->myclassObject = $this->getMockBuilder('MyVendor\MyModule\Model\Foo')
    ->setMethods(['__construct'])        
    ->setConstructorArgs(['$logger'])
    ->disableOriginalConstructor()
    ->getMock();

    public function testBar()
    {

        $this->assertEquals($expected_result,$this->myclassObject->Bar());
    }
}

我希望看到使用存根调试方法记录“消息记录”的成功单元测试

【问题讨论】:

    标签: php phpunit


    【解决方案1】:

    我忽略了在类级别定义 $this->myclassObject 的语法问题,因为我认为这是您创建此问题时的拼写错误。

    认为你有两个问题:

    • 您通过在 LoggerInterface 的 setMethods 中指定 null 来覆盖 PHPUnit 模拟类/接口的抽象/接口方法的能力,这告诉它不要模拟任何东西
    • 您同时禁用了 Foo 构造函数提供构造函数参数(在引号中作为变量名的标量值)

    您还引用了不存在的$logger

    我还建议在您的示例中,您根本不需要部分模拟 Foo,因为此时您没有模拟它的任何功能。您可以直接拨打new Foo($this->logger)。但是,我假设您的示例已被删减,并且您确实需要部分模拟该类的其他部分,因此暂时将其保留。

    试试这个:

    class FooTest extends TestCase
    {
        private $logger;
        private $myclassObject;
    
        protected function setUp()
        {
            $this->logger = $this->createMock('\Psr\Log\LoggerInterface');
    
            $this->logger->expects($this->any())
                ->method('debug')
                ->willReturn('Message Logged');
    
            $this->myclassObject = $this->getMockBuilder('\MyVendor\MyModule\Model\Foo')
                ->setConstructorArgs([$this->logger])
                ->getMock();
        }
    
        public function testBar()
        {
            $this->assertEquals($expected_result, $this->myclassObject->Bar());
        }
    }
    

    【讨论】:

    • 感谢 myclassObject 的更正。在我看来,我认为 disableOriginalConstructor 需要在 Foo Mock 中使用,因为我们正在存根记录器调试方法。此外,此“记录的消息”将保存在哪里。我在 debug.log 中找不到它应该保存在这里吗?
    • 你在模拟记录器,所以它不会在任何地方记录。您可以运行断言它会在您的模拟上被调用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多