Mockery和PHPUnit:此模拟对象上不存在方法

Per*_*ika 5 php phpunit unit-testing mocking mockery

你能告诉我问题出在哪里吗?我有一个文件GeneratorTest.ph p与以下测试:

<?php

namespace stats\Test;

use stats\jway\File;
use stats\jway\Generator;

class GeneratorTest extends \PHPUnit_Framework_TestCase
{

    public function tearDown() {
        \Mockery::close();
    }

    public function testGeneratorFire()
    {
        $fileMock = \Mockery::mock('\stats\jway\File');
        $fileMock->shouldReceive('put')->with('foo.txt', 'foo bar')->once();
        $generator = new Generator($fileMock);
        $generator->fire();
    }

    public function testGeneratorDoesNotOverwriteFile()
    {
        $fileMock = \Mockery::mock('\stats\jway\File');
        $fileMock->shouldReceive('exists')
            ->once()
            ->andReturn(true);

        $fileMock->shouldReceive('put')->never();

        $generator = new Generator($fileMock);
        $generator->fire();
    }
}
Run Code Online (Sandbox Code Playgroud)

这里是文件生成器类:

File.php:

class File
{
    public function put($path, $content)
    {
        return file_put_contents($path, $content);
    }

    public function exists($file_path)
    {
        if (file_exists($file_path)) {
            return true;
        }
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

Generator.php:

class Generator
{
    protected $file;

    public function __construct(File $file)
    {
        $this->file = $file;
    }

    protected function getContent()
    {
        // simplified for demo
        return 'foo bar';
    }

    public function fire()
    {
        $content = $this->getContent();
        $file_path = 'foo.txt';

        if (! $this->file->exists($file_path)) {
            $this->file->put($file_path, $content);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

因此,当我运行这些测试时,我收到以下消息:BadMethodCallException:Method ... :: exists()在此模拟对象上不存在.

在此输入图像描述

Bra*_*sen 8

错误消息对我来说似乎很清楚.您只设置了该put方法的期望,但没有exists.exists所有代码路径中的测试类都会调用该方法.

public function testGeneratorFire()
{
    $fileMock = \Mockery::mock('\stats\jway\File');
    $fileMock->shouldReceive('put')->with('foo.txt', 'foo bar')->once();

    //Add the line below
    $fileMock->shouldReceive('exists')->once()->andReturn(false);

    $generator = new Generator($fileMock);
    $generator->fire();
}
Run Code Online (Sandbox Code Playgroud)

  • 你必须添加 `shouldIgnoreMissing()` 来让模拟对象在你没有设置期望时返回 null。在这种情况下,严格并返回 false 会更好,因为布尔值是 `exists` 的接口定义的。如果你将 `if (! $this-&gt;file-&gt;exists($file_path))` 重写为 `if ($this-&gt;file-&gt;exists($file_path) === false))` 你的单元测试将会中断。 (2认同)