PHPUnit 中的 Mock - 使用不同参数对同一方法进行多次配置

2022-08-30 10:28:30

是否可以以这种方式配置 PHPUnit 模拟?

$context = $this->getMockBuilder('Context')
   ->getMock();

$context->expects($this->any())
   ->method('offsetGet')
   ->with('Matcher')
   ->will($this->returnValue(new Matcher()));

$context->expects($this->any())
   ->method('offsetGet')
   ->with('Logger')
   ->will($this->returnValue(new Logger()));

我使用PHPUnit 3.5.10,当我要求匹配器时,它失败了,因为它需要“Logger”参数。这就像第二个期望正在重写第一个期望,但是当我抛弃模拟时,一切看起来都还好。


答案 1

可悲的是,使用默认的PHPUnit Mock API无法做到这一点。

我可以看到两个选项可以让你接近这样的东西:

使用 ->at($x)

$context = $this->getMockBuilder('Context')
   ->getMock();

$context->expects($this->at(0))
   ->method('offsetGet')
   ->with('Matcher')
   ->will($this->returnValue(new Matcher()));

$context->expects($this->at(1))
   ->method('offsetGet')
   ->with('Logger')
   ->will($this->returnValue(new Logger()));

这将正常工作,但您正在测试比您应该测试的更多(主要是首先使用匹配器调用它,这是一个实现细节)。

此外,如果您对每个函数有多个调用,这将失败!


接受这两个参数并使用 returnCallBack

这是更多的工作,但工作更好,因为你不依赖于调用的顺序:

工作实例:

<?php

class FooTest extends PHPUnit_Framework_TestCase {


    public function testX() {

        $context = $this->getMockBuilder('Context')
           ->getMock();

        $context->expects($this->exactly(2))
           ->method('offsetGet')
           ->with($this->logicalOr(
                     $this->equalTo('Matcher'), 
                     $this->equalTo('Logger')
            ))
           ->will($this->returnCallback(
                function($param) {
                    var_dump(func_get_args());
                    // The first arg will be Matcher or Logger
                    // so something like "return new $param" should work here
                }
           ));

        $context->offsetGet("Matcher");
        $context->offsetGet("Logger");


    }

}

class Context {

    public function offsetGet() { echo "org"; }
}

这将输出:

/*
$ phpunit footest.php
PHPUnit 3.5.11 by Sebastian Bergmann.

array(1) {
  [0]=>
  string(7) "Matcher"
}
array(1) {
  [0]=>
  string(6) "Logger"
}
.
Time: 0 seconds, Memory: 3.00Mb

OK (1 test, 1 assertion)

我已经在匹配器中使用了,以表明这也适用于计算调用。如果你不需要把它换成意志,当然,工作。$this->exactly(2)$this->any()


答案 2

从 PHPUnit 3.6 开始,有$this->returnValueMap(),它可用于根据给定参数向方法存根返回不同的值。


推荐