[英]Testing constructors with multiple arguments using PHPUnit
Given the following Value
object (no publicly accessible setters
): 给定以下
Value
对象(没有可公开访问的setters
):
class Address
{
public function __construct(string $addressLine1, string $addressLine2 = null, string $town, string $county, PostcodeInterface $postcode)
{
if (!$this->validateAddressLine($addressLine1)) {
throw new \InvalidArgumentException(...);
}
$this->addressLine1 = $this->normaliseAddressLine($addressLine1);
...
}
private function validateAddressLine(string $addressLine)
{
...
}
private function normaliseAddressLine(string $addressLine)
{
...
}
}
I have the following test class: 我有以下测试课:
class AddressTest extends PHPUnit\Framework\TestCase
{
public function invalidConstructorArgs()
{
return [
['1/1 Greenbank Road', '%$', 'city', 'county', new Postcode('123FX')]
];
}
/**
* @test
* @dataProvider invalidConstructorArgs
*/
public function constructor_with_invalid_args_throws_exception($addressLine1, $addressLine2, $town, $county, $postcode)
{
$this->expectedException(\InvalidArgumentException::class);
$address = new Address($addressLine1, $addressLine2, $town, $county, $postcode);
}
}
As you can see I am currently using a DataProvider
to supply my unit test with data. 如您所见,我当前正在使用
DataProvider
向单元测试提供数据。 Doing so results in a large array of values to be tested which are all written manually. 这样做会导致要测试的值的数组很大,这些值都是手动编写的。 Each argument is validated by an appropriate private method.
每个参数都通过适当的私有方法进行验证。 Currently to test those methods I am writing a data provider which contains valid and invalid argument values to test these methods (as below):
当前要测试这些方法,我正在编写一个数据提供程序,其中包含有效和无效的参数值来测试这些方法(如下所示):
// test validation on first argument
["invalid", "valid", "valid", "valid", "valid"],
...
// test validation on second argument
["valid", "invalid", "valid", "valid", "valid"],
...
// test validation on third argument
["valid", "valid", "invalid", "valid", "valid"],
...
// etc.
Is there something in PHPUnit I should be making use of that I have overlooked for this type of scenario? 对于这种情况,PHPUnit中是否有我应该利用的东西?
I agree with your comment that having validation logic in your value object is a matter of taste, but one major drawback is that it does make unit-testing harder, as you're seeing. 我同意您的意见,即在值对象中包含验证逻辑只是一个问题,但是一个主要缺点是,正如您所看到的,它确实使单元测试变得更加困难。 If your value object is now responsible for two things (data storage and validation), then testing gets more complicated, especially if you've made the validation logic private.
如果您的值对象现在负责两件事(数据存储和验证),则测试会变得更加复杂,尤其是在您将验证逻辑设为私有的情况下。
One approach you might want to consider is to use Reflection to test your private methods directly. 您可能要考虑的一种方法是使用Reflection直接测试您的私有方法。 You'll find a lot of debate about whether this is bad practice in some of the related questions linked to the side of this one, which I won't go over again here.
在与此问题相关的一些相关问题中,您会发现很多关于这种做法是否不好的争论,在此我不再赘述。 For my own point of view, I think this is one of the few cases where it makes sense.
以我自己的观点,我认为这是有意义的少数情况之一。
You can use something like this to run a private method from the unit test directly: 您可以使用以下方法直接从单元测试中运行私有方法:
/**
* @test
* @dataProvider invalidAddressLine1Provider
*/
public function invalid_parameter_throws_exception($invalidParameter)
{
$reflector = new \ReflectionClass(Foo::class);
// The call to newInstanceWithoutConstructor here is important, since the
// constructor is what we're looking to avoid
$instance = $reflector->newInstanceWithoutConstructor();
$method = $reflector->getMethod('validateAddressLine1');
$method->setAccessible(true);
$this->expectException(\Exception::class);
$method->invoke($instance, $invalidParameter);
}
You could also combine the invalid parameters for all validation methods into a single dataProvider, and pass the method name in as an argument, to save duplicating the Reflection code. 您还可以将所有验证方法的无效参数组合到单个dataProvider中,并将方法名称作为参数传递,以节省重复的反射代码。
public function invalidProvider()
{
return [
['validateAddressLine1', 'invalid value for line 1'],
['validateAddressLine2', 'invalid value for line 2'],
// ...
];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.