Поблочное тестирование метод, который называет другой метод

Неустранимая ошибка: вызов функции-члена ... на не-объект

происходит с кодом, подобным xyz->method(), где xyz не является объектом и, следовательно, method не может

Это фатальная ошибка, которая остановит сценарий (уведомление о прямой совместимости: это станет захватывающей ошибкой, начиная с PHP 7).

Чаще всего это знак что в коде отсутствуют проверки условий ошибок. Убедитесь, что объект фактически является объектом перед вызовом его методов.

Пример типичного будет

// ... some code using PDO
$statement = $pdo->prepare('invalid query', ...);
$statement->execute(...);

В приведенном выше примере запрос не может и prepare() назначит false на $statement. Попытка вызвать метод execute() приведет к Fatal Error, потому что false является «не объектом», потому что значение является логическим.

Выясните , почему ваша функция вернула логическое значение вместо объекта. Например, проверьте объект $pdo для последней произошедшей ошибки. Подробности о том, как отлаживать это, будут зависеть от того, как обрабатываются ошибки для конкретной рассматриваемой функции / объекта / класса.

Если даже сбой ->prepare не выполняется, то ваш дескриптор

// ... some code using PDO
$statement = $pdo->prepare('invalid query', ...);
$statement->execute(...);

базы данных

// ... some code using PDO
$statement = $pdo->prepare('invalid query', ...);
$statement->execute(...);

не попал в текущий объем . Найдите, где он определился. Затем передайте его как параметр, сохраните его как свойство или поделите его через глобальную область.

Другой проблемой может быть условное создание объекта, а затем попытка вызова метода вне этого условного блока. Например,

if ($someCondition) {
    $myObj = new MyObj();
}
// ...
$myObj->someMethod();

Пытаясь выполнить метод вне условного блока, ваш объект не может быть определен.

Вопросы, относящиеся:

57
задан Anton Rudeshko 1 March 2015 в 16:32
поделиться

11 ответов

Это - классический основанный на состоянии тест по сравнению с основанным на поведении сценарием тестирования.

В этом смехотворно простом примере, тестирующем вывод, прекрасен. В какой-то момент, хотя, Вы столкнетесь с тестами, где, осматривая состояние после того, как выполнение является сложным. Вместо этого Вы хотите проверить поведение (например, проверить, что changeit назвали с определенным значением).

В той точке, вероятно, необходимо изучить платформу фиктивного объекта как Носорог. Насмешки (.Net) или Mockito (Java) и начинают писать больше основанного на интерфейсе кода.

38
ответ дан Eric Nicholson 24 November 2019 в 19:38
поделиться

У Вас есть много опций. То, какой является лучшим, зависит от деталей, которые не ясны из Вашего вопроса.

  • тест modify так же, как если бы это был несвязанный метод. Преимущество: это могло бы в какой-то момент стать тем.
  • просто тест, что Вы разобрались в операторе "if". Таким образом, просто протестируйте достаточно, что тесты вынуждают Вас записать реализацию, в которой Вы нуждаетесь (где вызов replaceit и changeit просто самая простая реализация, которая могла возможно работать . Если Ваш практикуют TDD, это должно прибыть естественно к Вам. Преимущество: высокое тестовое покрытие без очень дублированного усилия.
  • Метод подклассов и Переопределенный метод (это - метод повреждения зависимости из книги, "Работающей Эффективно С Унаследованным кодом"): Протестируйте метод на подклассе, который Вы представляете только для тестирования, который переопределяет replaceit и changeit с консервированными ответами или так, чтобы они установили распознающиеся переменные (переменные, которые указывают, назвали ли метод с правильным значением (значениями)). Преимущество: мог бы возможно упростить Ваши тесты (или не), иногда даже просто сделайте тестирование возможным.
  • Извлечение новый класс для replaceit и changeit методы, включая интерфейс для того класса. Тупик или Насмешка, которые взаимодействуют через интерфейс при тестировании modify. Преимущество: мог бы и сделать Ваш дизайн больше тестируемый и лучше разъединенный/допускающий повторное использование в целом (или не).
17
ответ дан Ilja Preuß 24 November 2019 в 19:38
поделиться

Просто тест modify.

Modify, как предполагается, возвращает определенные значения, когда дали определенные значения.

Это неважно , как изменяют, делает его задание - только, что это делает его задание.

И если в будущем Вы изменяетесь modify для использования различных методов (или никаких методов), оно не делает, и не должен, и не быть, влиять тесты.

Однако также протестируйте replaceit' and changeit'.

6
ответ дан Ian Boyd 24 November 2019 в 19:38
поделиться

Если Вы уже протестировали replaceit() и changeit() независимо, то единственная вещь, которую Вы оставили тесту, если условие. Тест modify() с несколькими значениями для проверки это вызывает правильную функцию при правильных условиях (те условия, являющиеся null и Strings из длины 4, 5, и 6 для примера кода, который Вы дали).

15
ответ дан Janis S. 24 November 2019 в 19:38
поделиться

В порядке предпочтения

  1. изменяют (тестируют), просто имеет 2 сценария (каждая рука, если бы stmt), таким образом, я записал бы, что 2 теста для изменяют формы.
    , Если ожидаемый результат replaceit (значение) легко определить..

.

public TestModifyIfValueLength..()
    {
      string expectedValue = .. ;// literal result of replaceit(value)
      Assert.Equals( expectedValue, modify("asd") );
    }
  1. В противном случае рассматривают использование тупика (используйте подкласс и переопределите changeit, replaceit) проверить, что корректный метод назвали.
  2. , Если тупик является слишком большой работой, сделайте Ложную вещь. Извлеките интерфейс и установите ожидания по changeit, replaceit.

Предположения

  • у Вас есть тесты для replaceit (значение) и changeit (значение), которые тестируют (например, все граничные условия для) те 2 метода всесторонне.
  • replaceit () и changeit () являются открытыми методами.. В противном случае необходимо рассмотреть тесты записи против открытых методов только. Необходимо быть свободны настроить / выгоняют закрытые методы без знания тестового кода.
5
ответ дан Gishu 24 November 2019 в 19:38
поделиться

Каков "тестовый код" в этом случае? Установка и проверка результатов? Если так, я осуществил бы рефакторинг его в различный метод и использовал бы его от каждого из тестов. Я только сделал бы это, если существует sigificant сумма его хотя - существует преимущество удобочитаемости для способности видеть все, что тест делает, только путем чтения кода того метода.

Сложные методы тестирования часто беспокоят меня для начала, чтобы быть честными - часто их нельзя реалистично избежать, но если Вы можете упрощать их, это стоит сделать так.

4
ответ дан Jon Skeet 24 November 2019 в 19:38
поделиться

Ну, нет, Ваш тестовый код не будет 99% то же, потому что Вы на самом деле тестируете что-то другое здесь, если replaceit, changeit и не изменяют весь возврат те же значения.

Не уверенный, почему трудность. Тест для изменить метода должен быть приблизительно четырьмя строками долго. Так как Вы уже тестируете базовую функциональность и все, что Вы хотите сделать, удостоверяются, что этот конкретный метод не повреждается, пишущий тест, который тестирует два возможных пути выполнения кода в этом функциональном возврате, математические ожидания должны быть достаточными.

2
ответ дан TheSmurf 24 November 2019 в 19:38
поделиться

Если бы Вы уже записали тесты для replaceit () и changeit (), тест для изменяет, просто проверил бы, что различные результаты возвращаются в зависимости от значения 'значения'. Однако Вы будете просто повторно реализовывать логику метода в тесте, который немного абсурден.

В этом случае я не протестировал бы, изменяют, пока это не имеет более сложную логику, или лучше - используется другим методом, который является более значительным протестировать.

2
ответ дан Eran Galperin 24 November 2019 в 19:38
поделиться

Вам в основном нужны 2 теста.

1) Передача в строке как "Быстрые Переходы Brown Fox!" (длина, больше, чем пять), удостоверяется, что значение затронуто replaceit(...)

2) Передача в строке как "Нечто" (длина - меньше чем пять), и удостоверьтесь, что значение затронуто changeit(...)

, Ваш тест (в псевдо коде) мог бы быть похожим на это:

testLongValue() {
    string testValue = "A value longer than 5 chars";
    string expected = "Replaced!";
    string actual = modify(testValue);
    assertEqual(expected, actual);
}

testShortValue() {
    string testValue = "len4";
    string expected = "Changed!";
    string actual = modify(testValue);
    assertEqual(expected, actual);
}

, Очевидно, я мог дать Вам более реалистический пример, если бы я знал то, что replacit () и changeit (), как предполагалось, сделали, но это должно дать Вам идею. Если это видоизменяет ссылку исходного значения вместо того, чтобы возвратить его, можно просто использовать testValue в качестве фактического значения после того, как вызов происходит.

2
ответ дан Justin Standard 24 November 2019 в 19:38
поделиться

При тестировании граничных условий как if (value.length > 5) необходимо удостовериться, что данные тестирования содержат значения value, которые имеют длину 4, 5, или 6.

2
ответ дан Brian Matthews 24 November 2019 в 19:38
поделиться

То же как Justin Standard, плюс передача null как значение (который, очевидно, будет сбои для фрагмента кода, который Вы даете нам;)) Основное правило для Поблочного тестирования является "тестом только, что характерно для метода под тестом". И это вполне... редкий для имения метода, который не называет другой.

0
ответ дан Olivier 24 November 2019 в 19:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: