У меня есть метод, который создает большой многомерный массив.Я пытаюсь запустить серию модульных тестов по этому методу.Я пытаюсь сделать как положительные тесты (тестирование, что определенные ключи массива установлены), так и отрицательные тесты (тестирование, что определенные ключи массива отсутствуют).Проблема в том, что для настройки объекта требуется много кода, и существует множество различных аргументов, которые этот метод принимает, и которые я хочу протестировать.По этим причинам я хочу использовать провайдеров данных для запуска серии тестов метода.Таким образом, я мог бы настроить объект один раз и использовать поставщик данных для получения аргументов массива и ожидаемых значений массива.
Я могу выполнить положительные тесты, вызвав $this->assertArraySubset()
и включивожидаемая структура массива в поставщике данных.Но я не могу придумать хороший способ проверить, что определенные ключи массива не существуют (мой отрицательный тест), потому что эти ключи массива находятся на разных уровнях массива.
Вот пример моего кодатак что вы можете видеть, с чем я имею дело:
<?php
class MyClassTest {
public function providerForFunctionThatCreatesArray() {
return [
[
'{foo:bar}', # some data returned by service A
'{foo:baz}', # some data returned by service B
'c' # checking that this key does not exist in the array
],
[
'{foo:barbaz}',
'{foo:bazbar}',
'd' # I also want to check that this key does not exist but in a different level of the array (i.e. $array['b'])
],
]
}
/**
* @dataProvider providerForFunctionThatCreatesArray
*/
public function testFunctionThatCreatesArray($dataFromServiceA, $dataFromServiceB, $expectedKeyNotExists) {
$serviceA = $this
->getMockBuilder(ServiceA::class)
->setMethods(['get_data'])
->getMock();
$serviceA->expects($this->any())->method('get_data')->willReturnValue($dataFromServiceA);
$serviceB = $this
->getMockBuilder(ServiceB::class)
->setMethods(['get_data'])
->getMock();
$serviceB->expects($this->any())->method('get_data')->willReturnValue($dataFromServiceB);
$myClass = new MyClass($serviceA, $serviceB);
$array = $myClass->functionThatCreatesArray();
// This is the function that checks that keys do not exist in the array
$this->assertArrayNotHasKey($expectedKeyNotExists, $array['a']);
}
}
Материал {foo:...}
- это данные, возвращаемые некоторыми службами, которые использует моя функция.Различные значения влияют на массив, который создает моя функция.Я создал макеты для этих сервисов и использую провайдера данных, чтобы принудительно установить значение, возвращаемое сервисами.
Как видите, мой провайдер данных также возвращает ключ в качестве третьего аргумента моей тестовой функции ($expectedKeyNotExists
).Этот ключ, который я проверяю, не существует в моем массиве.Однако ключ d
- это ключ, который я хочу проверить в другой части моего массива, например, $array['b']
вместо $array['a']
.Если я выполню вышеуказанный тест, он проверит, что «d» не существует в $array['a']
, что не то, что я хочу. Что может быть хорошим способом структурировать мои тесты для динамической проверки того, что мои ключи не существуют в разных частях массива?
Я думал о том, чтобы мой поставщик данных возвратил четвертый ключ, которыйродительский ключ для использования.Вот так:
return [
[
'{foo:bar}', # some data returned by service A
'{foo:baz}', # some data returned by service B
'c', # checking that this key does not exist in the array
'a' # parent key
],
[
'{foo:barbaz}', # some data returned by service A
'{foo:bazbar}', # some data returned by service B
'd', # checking that this key does not exist in the array
'b' # parent key
]
]
И тогда я мог бы сделать свои тесты следующим образом:
public function testFunctionThatCreatesArray($dataFromServiceA, $dataFromServiceB, $expectedKeyNotExists, $parentKey) {
// ... snip ...
$this->assertArrayNotHasKey($expectedKeyNotExists, $array[$parentKey]);
}
Проблема с описанным выше методом заключается в том, что он не очень гибок в случае проверки ключей приразные уровни массива.Например, что если я хочу проверить, что ключи не существуют в $array['a']['e']['f']
и $array['a']['g']['h']
.