【问题标题】:PHPUnit mock using mockPHPUnit mock 使用 mock
【发布时间】:2015-04-04 05:57:29
【问题描述】:

我有两个类,我想通过 PHPUnit 测试它。 但是我在嘲笑这些东西时做错了一些事情。我想改变一个由第一类调用的方法。

class One {
    private $someVar = null;
    private $abc = null;

    public function Start() {
        if ( null == $this->someVar) {
            $abc = (bool)$this->Helper();
        }

        return $abc;
    }

    public function Helper() {
        return new Two();
    }


}
Class Two {
    public function Check($whateverwhynot) {
        return 1;
    }
}


Class testOne extends PHPUnit_Framework_TestCase {
    public function testStart() {
        $mockedService = $this
            ->getMockBuilder(
                'Two',
                array('Check')
            )
            ->getMock();

        $mockedService
            ->expects($this->once())
            ->method('Check')
            ->with('13')
            ->will($this->returnValue(true));

        $mock = $this
            ->getMockBuilder(
                'One',
                array('Helper'))
            ->disableOriginalConstructor()
            ->getMock();

        $mock
            ->expects($this->once()) 
            ->method('Helper')
            ->will($this->returnValue($mockedService));

        $result = $mock->Start();
        $this->assertFalse($result);
    }
}

结果是$resultNULL,而不是'true'

如果我不使用断言行,我会收到一条错误消息:

F

Time: 0 seconds, Memory: 13.00Mb

There was 1 failure:

1) testOne::testStart
Expectation failed for method name is equal to <string:Check> when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.

想法?

更新 - 环境:PHP 5.4.3x,PHPUnit 3.7.19 - 重要的一点:不能修改原来的类(一类和二类)

【问题讨论】:

  • PHPUnit 用于依赖注入。您需要将模拟的 Two 类注入 One。另外你没有正确使用 getMockBuilder 方法的参数。
  • getMockBuilder 在哪里使用不好?如何将第二个模拟类注入第一个模拟类?我没有找到任何示例或文档或任何相关内容,您可以删除链接或其他内容吗?

标签: php dependency-injection mocking phpunit unit-testing


【解决方案1】:

您可以使用来自ouzo-goodies 的模拟。

类:

class One
{
    private $someVar = null;
    private $abc = null;
    private $two;

    public function __construct(Two $two)
    {
        $this->two = $two;
    }

    public function Start()
    {
        if (null == $this->someVar) {
            $abc = (bool)$this->Helper()->Check(1213);
        }

        return $abc;
    }

    public function Helper()
    {
        return $this->two;
    }
}

在构造函数中注入对象Two,因此您可以轻松地模拟该对象。

class Two
{
    public function Check($whateverwhynot)
    {
        return 1;
    }
}

和测试:

class OneTest extends PHPUnit_Framework_TestCase
{
    /**
     * @test
     */
    public function shouldCheckStart()
    {
        //given
        $mock = Mock::create('\Two');
        Mock::when($mock)->Check(Mock::any())->thenReturn(true);

        $one = new One($mock);

        //when
        $start = $one->Start();

        //then
        $this->assertTrue($start);
    }
}

mocks 的文档。

【讨论】:

  • 好点,谢谢!....但主要问题是,我不能修改原来的 One 和 Two 类,也不能使用任何 3rd 方库进行测试。跨度>
【解决方案2】:

您创建的模拟错误。您正在使用$this-&gt;getMockBuilder(),它只接受一个参数,即要模拟的类的名称。您似乎将它与需要多个的 $this-&gt;getMock() 混为一谈。

将测试改为:

public function testStart() {
    $mockedService = $this
        ->getMockBuilder('Two')
        ->setMethods(array('Check'))
        ->getMock();

    $mockedService
        ->expects($this->once())
        ->method('Check')
        ->with('13')
        ->will($this->returnValue(true));

    $mock = $this
        ->getMockBuilder('One')
        ->setMethods(array('Helper'))
        ->disableOriginalConstructor()
        ->getMock();

    $mock
        ->expects($this->once()) 
        ->method('Helper')
        ->will($this->returnValue($mockedService));

    $result = $mock->Start();
    $this->assertFalse($result);
}

这不是一个好的测试,因为我们需要模拟我们正在测试的类,但您说您根本无法更改这些类。

【讨论】:

  • 感谢帮助,它正在工作。在其他情况下,注入也有效&&是的,我真的错误地使用了模拟构建器。再次感谢!
  • 最好重构类,这样你就可以使用依赖注入但是如果你不能改变类......
猜你喜欢
  • 1970-01-01
  • 2012-10-22
  • 2011-11-23
  • 2020-01-25
  • 2017-10-14
  • 1970-01-01
  • 2017-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多