В тестовых классах приложения DreamHouse Sample все функции имеют следующую структуру:

static testMethod void testSomething() {
    Boolean success = true;
    try {
        ...
    } catch (Exception e) {
        success = false;
    } finally {
        System.assert(success);
    }
}

Источник: https://github .com/dreamhouseapp/dreamhouse-sfdx/blob/master/force-app/main/default/classes/PropertyControllerTest.cls

В чем причина или преимущество этой структуры?

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

Спасибо!

10
Community 15 Июн 2020 в 11:11
3
Мне любопытно посмотреть, есть ли ответ на обратное, но я не вижу преимуществ этой структуры и не думаю, что это лучшая практика. Я бы сам назвал эти дымовые тесты; утверждение ничего не доказывает и на самом деле скрывает исключение, которое могло содержать ценную информацию.
 – 
David Reed
16 Дек 2018 в 03:27
1
Если бы я собирался быть педантичным, я бы также назвал использование устарело testMethod, а не @IsTest.
 – 
Daniel Ballinger
17 Дек 2018 в 01:30
Я думаю, что «Чистый код» и «Лучшие практики кодирования», кроме «Доведение дела до конца», не входят в топ-список ни одного евангелиста разработчиков в Salesforce. ;-)
 – 
Robert Sösemann
9 Янв 2019 в 00:51

3 ответа

Лучший ответ

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

Фактически, вы должны использовать try-catch только в том случае, если ожидаете определенного исключения:

try {
  doSomething();
  System.assert(false, 'Expected to get an exception');
} catch(SpecificException e) {
  // Good, but maybe System.assert for a specific message, etc
}

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

10
sfdcfox 16 Дек 2018 в 04:25

Платформа тестирования сообщает об исключениях как об ошибках, поэтому пусть она сделает всю работу за вас. Затем ваш пример вопроса упрощается до:

@IsTest
static void something() {
    ...
}

Это Простота в разработке программного обеспечения: Запись в блоге KISS, YAGNI и Occam's Razor актуальна здесь и содержит эту прекрасную цитату:

Совершенство достигается не тогда, когда больше нечего добавить, а когда нечего убирать.

Я вижу, что не все тесты DreamHouse используют этот шаблон. BotTest не . Возможно, код try/catch/finally пытался выразить мысль о том, что тест предназначен для проверки исключений. Комментарий был бы хорошим способом сообщить об этом.

5
Keith C 16 Дек 2018 в 12:42
1
+1 Это так верно. Зачем писать в 7 строк то, что можно написать в 0?
 – 
sfdcfox
16 Дек 2018 в 20:21
1
Интересно, обязали ли они, чтобы все методы тестирования делали утверждение? Эти тестовые случаи больше похожи на наполнитель для покрытия. PropertyController.getPropertyList() возвращает Property__c[]. ИМХО было бы лучше делать утверждения о тех записях.
 – 
Daniel Ballinger
17 Дек 2018 в 01:23

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

Наши передовые методы

SpecificException unexpectedException;
Test.startTest();
    try
    {
        // logic here
    }
    catch (SpecificException e)
    {
        unexpectedException = e;
    }
Test.stopTest();

system.assertEquals(null, unexpectedException, 'Informative message');

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

Существуют вариации антишаблона, которые нарушают эту аксиому, но один типичный пример приведен ниже.

Анти-шаблон

Test.startTest();
    try
    {
        // logic here
    }
    catch (SpecificException e)
    {
        system.assert(false, 'Informative message');
    }
Test.stopTest();

Этот антишаблон нарушает нашу аксиому о том, что каждое утверждение должно быть безусловным.

Приложение

Паттерн, продемонстрированный в приложении, не допускает нарушения аксиомы, поэтому сам паттерн, вероятно, пройдет проверку кода. Однако было бы заметным улучшением кэшировать конкретный экземпляр Exception, а не флаг Boolean, и, на мой взгляд, вложение блоков таким образом менее очевидно.

И последнее замечание: мы твердо считаем не лучшей практикой отлавливать общие Exception, также называемые в просторечии "поймать покемонов"). Вы должны знать, какой тип исключения вы ожидаете, и обрабатывать именно его. Таким образом, в то время как шаблон try/catch/finally прошел проверку кода (с комментариями), этот аспект кода не прошел.

3
Adrian Larson 16 Дек 2018 в 04:20
Интересная теория, но почему вы советуете это вместо того, чтобы вообще не использовать try-catch и просто позволить исключению не пройти тест напрямую? Это дает вам немедленную ошибку и трассировку стека без дополнительных утверждений и т. д. Я бы лучше сосредоточился на написании утверждений, которые доказывают, что все работает успешно, а не на проверке конкретных исключений, которые мы можем получить.
 – 
sfdcfox
16 Дек 2018 в 04:31
Кроме того, «этот антишаблон нарушает нашу аксиому о том, что каждое утверждение должно быть безусловным». Вы не имеете в виду "условно"?
 – 
sfdcfox
16 Дек 2018 в 04:34
Мы уже обсуждали это в комментариях к другим темам. Мы утверждаем, что тесты должны только завершаться ошибкой из-за утверждения. Я знаю, что ты не согласен.
 – 
Adrian Larson
16 Дек 2018 в 05:23
Извините, я, должно быть, забыл. В последнее время у меня было много мыслей.
 – 
sfdcfox
16 Дек 2018 в 05:30
1
Ха-ха без обид. Это просто постоянный спор между нами (хотя я думаю, что мы согласны не соглашаться).
 – 
Adrian Larson
16 Дек 2018 в 05:50