PHPUNIT模拟方法可以接受任何参数

时间:2019-05-31 07:34:52

标签: php symfony mocking phpunit

我在这里和Symfony一起使用simple-phpunit from phpunit/phpunit-bridge

我有一个要测试的A类,其中使用了B类方法。

在模拟B及其方法时,我意识到它被称为多次并且具有多个参数:类名和整数。 我为此使用returnValueMap(),但有一个问题:PHPUNIT似乎要求我精确设置参数,使其在调用方法时准确地赋值。 我可以设置类名(它们有给定的可能数字,因此可以手动设置它们),但是给定的整数是任意的(并且该方法在循环中调用),因此无法精确设置它。

是否可以告诉PHPUNIT接受此函数的任何参数? 就像anyParameter()方法(在搜寻TestCase文件后找不到)。

如果我在测试和类方法中将Integer参数设置为固定值,则测试通过(但是,当然不能在类方法中将Integer设置为固定值)。

class ToBeTested{
     public $objectB;
     public function functionToTest($dataList){
        ......
        $objectB=new ObjectB();
        foreach($dataList as $data){
            $className=$data['className'];
            $integerNeeded=$data['integer'];
            //Here if $inetegerNeeded is not the exact value set in the Mock
            //$result will be null
            $result=$this->objectB->doSomething($className,$integerNeeded);
            if($result == null) throw new \Excpetion(" Object is null");
        }
        .....
     }
}

class UnitTest extends TestCase{
       /**
         $generatedDataList comes from a DataProvider 
          with some varied and exotic data close to real use cases
       **/
       public function testFunction($generatedDataList)
       {
           $mockOfObjectB= $this->getMockBuilder(ObjectB::class)
                 ->getMock();
          /**
      Here I'd like to use $this->anyParameter() or something that'd work that      way 
      If I set this to a fixed value here and in the functionToTest() method it   passes 
          **/
           $anyInteger=-1;  
           $dataReferenceMap= [
              ['ClassNameA',$anyInteger,new MockObject()],
              ['ClassNameB',$anyInteger,new MockObject()],
              ['ClassNameC',$anyInteger,new MockObject()],
           ];
           $mockOfObjectB
            ->expects($this->any())
            ->method('doSomething')
            ->will($this->returnValueMap($dataReferenceMap));
            $objectToTest = new ToBeTested();
            $objectToTest->objectB=$mockOfObjectB;

            //DO THE TESTING - will because of the parameter Fail 
            $objectToTest->functionToTest($generatedDataList);
          }
    }
}

我也可能错误地returnValueMap()吗?

对我来说这是很新的东西,我认为它的文档非常稀缺,并且不能很好地解释如何使用它。

1 个答案:

答案 0 :(得分:0)

我会选择willReturnCallback。这是示例(已通过phpunit 8.1检查)

<?php

declare(strict_types = 1);

use PHPUnit\Framework\TestCase;

final class SomeTest extends TestCase
{
    public function testSome()
    {
        $mock = $this
            ->getMockBuilder(\stdClass::class)
            ->setMethods(['doSomething'])
            ->getMock();
        $mock->method('doSomething')
            ->willReturnCallback(
                function (string $classname, int $int) {
                    $map = [
                    'ClassNameA' => 123,
                    'ClassNameB' => 345,
                    // ...
                    ];
                    return $map[$classname];
                }
            );
        $this->assertSame(123, $mock->doSomething('ClassNameA', 1));
        $this->assertSame(123, $mock->doSomething('ClassNameA', 1111111));
        $this->assertSame(345, $mock->doSomething('ClassNameB', 13456));
        $this->assertSame(345, $mock->doSomething('ClassNameB', 999999));
    }
}

这是->will($this->returnCallback(...))的快捷方式。 The doc