Mock in PHPUnit - multiple configuration of the same method with different arguments

前端 未结 7 735
死守一世寂寞
死守一世寂寞 2020-11-29 22:26

Is it possible to configure PHPUnit mock in this way?

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

$context->expects($this->any         


        
7条回答
  •  北海茫月
    2020-11-29 22:40

    Sadly this is not possible with the default PHPUnit Mock API.

    I can see two options that can get you close to something like this:

    Using ->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()));
    

    This will work fine but you are testing more than you should (mainly that it gets called with matcher first, and that is an implementation detail).

    Also this will fail if you have more than one call to each of of the functions!


    Accepting both parameters and using returnCallBack

    This is more work but works nicer since you don't depend on the order of the calls:

    Working example:

    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"; }
    }
    

    This will output:

    /*
    $ 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)
    

    I've used $this->exactly(2) in the matcher to show that this does also work with counting the invocations. If you don't need that swapping it out for $this->any() will, of course, work.

提交回复
热议问题