How to unit test the methods of a class whose cons

2020-07-10 08:43发布

问题:

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