【问题标题】:Is it possible to mock a method chained through an attribute?是否可以模拟通过属性链接的方法?
【发布时间】:2019-03-03 12:29:49
【问题描述】:

我有以下 PHP 函数,我正在尝试为其编写 PHPUnit 测试:

public function getDisplayMode()
{
    if($this->request->query->get('master_video'))
    {
        return 'listTranslations';
    }
    else
    {
        return 'default';
    }
}

$this->request->query->get('master_video') 行是我遇到的问题。

我已经模拟了request 对象,所以如果它只是$this->request->get('master_video'),我可以轻松地使用method 方法告诉我的系统get 应该返回什么。

但是当query 属性被假定存在时,我不知道该怎么做。 (例如,我不知道我的模拟对象上有任何 property 方法。)

有没有办法在这里定义get 方法应该返回的内容?

【问题讨论】:

    标签: php mocking phpunit


    【解决方案1】:

    创建query 的模拟并指定->get() 上发生的情况。测试最终看起来像这样:

    public function testGetDisplayMode() {
        $mockQuery = $this->getMockBuilder('Query') // Or whatever the query class is
             ->setMethods(['get'])
             ->getMock();
    
        $mockQuery->expects($this->once())
             ->method('get')
             ->with('master_video')
             ->willReturn('foo');
    
        $mockRequest = $this->getMockBuilder('Request') // Or whatever the request is
             ->getMock();
    
        $mockRequest->query = $mockQuery;
    
        $sut = new Bar($mockRequest) // Or however you instantiate the class with the mock request.
    
        $mode = $sut->getDisplayMode();
        // Do your assertions on the returned mode here.
    }
    

    作为一般规则,我发现当我做这样的事情时,我有一个模拟对象返回一个模拟对象,这是一种代码气味。您的方法在这里不需要 $this->request 它需要查询对象。您应该将其直接提供给对象或将其传递给此方法。

    如果不了解您正在制作的课程的更多信息,我无法提供更多建议。

    如果某些东西很难编写测试,则表明您没有优化设计代码。

    【讨论】:

    • 谢谢!这行得通。 (我也同意代码异味。这是我为无法修改的类编写测试的情况。)
    猜你喜欢
    • 2015-11-05
    • 1970-01-01
    • 2015-11-21
    • 2012-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多