问题
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 callsetMethods(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