php - 用于模拟由新类对象调用的方法的单元测试

标签 php mocking phpunit

我正在为这样的现有代码编写单元测试

class someClass {
    public function __construct() { ... }

    public function someFoo($var) {
        ...
        $var = "something";
        ...
        $model = new someClass();
        model->someOtherFoo($var);
    }

    public someOtherFoo($var){
         // some code which has to be mocked
    }
}

这里我应该如何模拟对函数“someOtherFoo”的调用,这样它就不会在 someOtherFoosome code”?

class someClassTest {
   public function someFoo() {
      $fixture = $this->getMock('someClass ', array('someOtherFoo'));
      $var = "something";
      ....
      // How to mock the call to someOtherFoo() here
   }

}

是否可以模拟构造函数以便它返回我自己构造的函数或变量?

谢谢

最佳答案

无论你在被测方法中的什么地方有 new XXX(...),你都注定失败。将实例化提取到同一类的新方法——createSomeClass(...)。这允许您创建被测类的部分模拟,从新方法返回 stub 或模拟值。

class someClass {
    public function someFoo($var) {
        $model = $this->createSomeClass();  // call method instead of using new
        model->someOtherFoo($var);
    }

    public function createSomeClass() {  // now you can mock this method in the test
        return new someClass();
    }

    public function someOtherFoo($var){
         // some code which has to be mocked
    }
}

在测试中,在调用someFoo() 的实例中模拟createSomeClass(),并在实例中模拟someOtherFoo()您从第一个模拟调用返回的实例。

function testSomeFoo() {
    // mock someOtherFoo() to ensure it gets the correct value for $arg
    $created = $this->getMock('someClass', array('someOtherFoo'));
    $created->expects($this->once())
            ->method('someOtherFoo')
            ->with('foo');

    // mock createSomeClass() to return the mock above
    $creator = $this->getMock('someClass', array('createSomeClass'));
    $creator->expects($this->once())
            ->method('createSomeClass')
            ->will($this->returnValue($created));

    // call someFoo() with the correct $arg
    $creator->someFoo('foo');
}

请记住,因为实例正在创建同一类的另一个实例,所以通常会涉及两个实例。如果更清楚的话,您可以在此处使用相同的模拟实例。

function testSomeFoo() {
    $fixture = $this->getMock('someClass', array('createSomeClass', 'someOtherFoo'));

    // mock createSomeClass() to return the mock
    $fixture->expects($this->once())
            ->method('createSomeClass')
            ->will($this->returnValue($fixture));

    // mock someOtherFoo() to ensure it gets the correct value for $arg
    $fixture->expects($this->once())
            ->method('someOtherFoo')
            ->with('foo');

    // call someFoo() with the correct $arg
    $fixture->someFoo('foo');
}

关于php - 用于模拟由新类对象调用的方法的单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7760635/

相关文章:

symfony - 独立 Symfony2 包中的功能测试

phpunit - 由于 PHPUnit 中的钩子(Hook)方法错误,测试被跳过

PHPUnit 数据提供者错误

php - Laravel 5.1 - 3 个表之间的数据透视表

PHP代码在网站上可见

php - SilverStripe MultiForm 不工作

php - 如果错误,则使用不同的参数开始循环?

python - 模拟 Django 模型类时无法重定向

使用防伪和环模拟测试 POST 路由

java - 我应该如何模拟 Jersey HTTP 客户端请求?