如何根据方法参数进行模拟


How to mock based on method parameter

我的一个存根模拟对象有一个方法,它将在我要测试的方法中调用两次。如何编写测试,以便覆盖测试方法中的两个分支?代码示例(存根对象是缓存):

public function myMethodToTest($param, $default) {
    if ($this->cache->has($param)) {
         return 'A';
    } else if ($this->cache->has($default)) {
         return 'B';
    }
}

从 phpunit 文档中解脱出来,我们可以从这个例子开始:

public function testObserversAreUpdated()
{
    // Create a mock for the Observer class,
    // only mock the update() method.
    $observer = $this->getMockBuilder('Observer')
                     ->setMethods(array('update'))
                     ->getMock();
    // Set up the expectation for the update() method
    // to be called only once and with the string 'something'
    // as its parameter.
    $observer->expects($this->once())
             ->method('update')
             ->with($this->equalTo('something'));
    // Create a Subject object and attach the mocked
    // Observer object to it.
    $subject = new Subject('My subject');
    $subject->attach($observer);
    // Call the doSomething() method on the $subject object
    // which we expect to call the mocked Observer object's
    // update() method with the string 'something'.
    $subject->doSomething();
}

注意方法调用with()。您可以使用它来指定将使用特定参数值调用该方法的期望,并指示在发生该方法时要返回的内容。 在您的情况下,您应该能够执行以下操作:

$cacheStub->method('has')
    ->with($this->equalTo('testParam1Value'))
    ->willReturn(true);

在一次测试中执行此操作,您将测试代码的一个分支。 在单独的测试中,您可以以不同的方式设置模拟:

$cacheStub->method('has')
    ->with($this->equalTo('testParam2Value'))
    ->willReturn(true);

此测试将测试您的其他分支。 如果您愿意,您可以将它们组合成一个测试,您可能需要在断言之间重新创建模拟。

另请参阅这篇简短的文章,其中有一些除$this->equalTo()之外的替代with()调用方式