How to unit test the methods of a class whose constructor take some arguments?

江枫思渺然 提交于 2020-05-26 01:22:10

问题


I have a class of form something like this:

class A{  
    public function __constructor(classB b , classC c){
    //
    }

    public function getSum(var1, var2){
        return var1+var2;
    }
}

My test case class is something like this:

use A;   
class ATest extends PHPUnit_Framework_TestCase{  

    public function testGetSum{  
        $a = new A();
        $this->assertEquals(3, $a->getSum(1,2));  
    }  
}  

However when I run the phpunit, it throws some error like:

Missing argument 1 for \..\::__construct(), called in /../A.php on line 5

Even if I provide the arguments, it throws the same error but in different file.
say, I instantiate by $a = new A(new classB(), new classC());

Then, I get the same error for the constructor of classB(the constructor of classB has similar form to that of A).

Missing argument 1 for \..\::__construct(), called in /../B.php on line 10

Is there any other way, I can test the function or something which I am missing.

I don't want to test by using mock (getMockBuilder(),setMethods(),getMock()) as it seems to defy the whole purpose of unit testing.


回答1:


The basic idea behind unit test it to test a class / method itself, not dependencies of this class. In order to unit test you class A you should not use real instances of your constructor arguments but use mocks instead. PHPUnit provides nice way to create ones, so:

use A;   
class ATest extends PHPUnit_Framework_TestCase{  

    public function testGetSum{  
        $arg1Mock = $this->getMock('classB'); //use fully qualified class name
        $arg2Mock = $this->getMockBuilder('classC')
            ->disableOriginalConstructor()
            ->getMock(); //use mock builder in case classC constructor requires additional arguments
        $a = new A($arg1Mock, $arg2Mock);
        $this->assertEquals(3, $a->getSum(1,2));  
    }  
}  

Note: If you won't be using mock's here but a real classB and classC instances it won't be unit test anymore - it will be a functional test




回答2:


You could tell to PHPUnit which method you want to mock of a specified class, with the methods setMethods. From the doc:

setMethods(array $methods) can be called on the Mock Builder object to specify the methods that are to be replaced with a configurable test double. The behavior of the other methods is not changed. If you call setMethods(null), then no methods will be replaced.

So you can construct your class without replacing any methods but bypass the construct as following (working) code:

public function testGetSum(){
    $a = $this->getMockBuilder(A::class)
        ->setMethods(null)
        ->disableOriginalConstructor()
        ->getMock();

    $this->assertEquals(3, $a->getSum(1,2));
}

Hope this help



来源:https://stackoverflow.com/questions/39390074/how-to-unit-test-the-methods-of-a-class-whose-constructor-take-some-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!