测试一个 class 方法调用另一个

Testing that one class method calls another

假设我有以下 class.

class SomeClass {

    public function shortcutMethod($arg1) {
        return $this->method($arg1, 'something');
    }

    public function method($arg1, $arg2) {
        // some stuff
    }

}

所以 shortcutMethod 是另一种方法的捷径。假设我想编写一个测试,给定 $arg1 shortcutMethod 将使用正确的参数正确调用 method

到目前为止,我认为我需要模拟 class 以期望使用一些参数调用 method,然后像这样在模拟对象上调用 shortcutMethod (注意我正在使用 Mockery)

$mock = m::mock("SomeClass");
$mock = $mock->shouldReceive('method')->times(1)->withArgs([
    'foo',
    'something'
]);

$mock->shortcutMethod('foo');

这会导致像这样的异常 shortcutMethod() does not exist on this mock object

我是不是误解了 mocking 的用法?我知道对于依赖注入到 class 的对象更有意义,但在这种情况下呢?你会怎么做?也许更重要的是,这种测试是否无用,如果是,为什么?

您应该使用模拟来模拟被测 class 的 dependencies,而不是被测 class 本身。毕竟,您正在尝试测试 class.

的真实行为

你的例子有点基础。如何测试这样的 class 取决于 method 函数的作用。如果它 returns 一个值又由 shortCutMethod 返回,那么我会说你应该只是断言 shortCutMethod 的输出。 method 函数中的任何依赖项都应该被模拟(属于其他 classes 的方法)。我不太熟悉嘲弄,但我已经对你的示例进行了调整。

class SomeClass {

   private $dependency;

   public function __construct($mockedObject) {
      $this->dependency = $mockedObject;
   }

   public function shortcutMethod($arg1) {
      return $this->method($arg1, 'something');
   }

   public function method($arg1, $arg2) {
      return $this->dependency->mockedMethod($arg1, $arg2);
   }

}

$mock = m::mock("mockedClass");

$mock->shouldReceive('mockedMethod')->times(1)->withArgs([
   'foo',
   'something'
])->andReturn('returnedValue');

$testCase = new SomeClass($mock);

$this->assertEquals(
   'returnedValue',
   $testCase->shortcutMethod('foo')
);

话虽如此,可以部分模拟您的 class 被测,以便您可以测试 shortCutMethod 函数的真实行为,但模拟 method 函数以断言它是用预期的参数调用的。看看部分模拟。

http://docs.mockery.io/en/latest/reference/partial_mocks.html