Знакомство с Apex. Часть 1

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

1. Вступление
2. Создание объекта и полей
3. Создание вспомогательного класса
4. Создание триггера
5. Написание юнит тестов
6. Deploy

Вступление

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

Создание объекта и полей

И так, начнём.

  1. Нажав на шестерёнку переходим на странице Setup на вашей dev org.
    image

  2. Переходим в Object manager | Create | Custom object
    image

  3. Указываем
    Label : Book
    Plural label : Books
    Дальше жмём Save.

  4. Оказавшись на странице нашего объекта Book, переходим в Field & Relationships, и создаём новое поле.

  5. Выбираем тип Number

  6. Указываем
    Field label : Price
    Length : 10
    Decimal Places : 2

    Потом жмём Next | Next | Finish.

Создание вспомогательного класса

Если вы уже создали объект Book и поле Price, тогда продолжим, создав вспомогательный класс с простенькой логикой для вычисления скидки на книгу.

В вашем рабочем окружении создаём класс BookPriceController и добавляем в него метод :

public with sharing class BookPriceController {

    public static void applyDiscount(List<Book__c> books) {
        for(Book__c b : books) {
            b.Price__c *= 0.9;
        }
    }
}

Давайте более детально рассмотрим метод.
Мы проходим в цикле по листу объектов типа Book__c, заметили что после имени объекта который мы создали добавилось __с , это является обозначением того что объект custom , т.е мы сами его создали. И при работе с Apex каждый используемый кастомный тип должен иметь такое окончание, за исключением SOQL запросов, там иногда требуется другое окончание, но об этом позже.
В цикле для каждой записи типа Book__c мы пересчитываем цену и тут же переписываем её, я думаю что вам уже знаком подобный код из Java или С#.

Создание триггера

  1. Создаём триггер(Apex Trigger). Называем его BookTrigger, указываем что триггер для объекта Book__c, во входных параметрах указываем Before Insert для того что бы перед тем как вставить нашу запись в базу данных salesforce мы могли обработать её в триггере.
trigger BookTrigger on Book__c (before insert) {
 
}
  1. Добавляем внутри триггера логику обработки:
  • List<Book__c> books = Trigger.new; - позволяет нам получить все записи типа Book__c и временно сохранить их в массив books. Да, я сказал массив, потому что в Apex, List = Array.
    Т.е List<Book__c> аналогично Book__c[ ].

  • BookPriceController.applyDiscount(books); - добавляем вызов нашего вспомогательного класса и передаем в него полученный массив книг.

trigger BookTrigger on Book__c (before insert) {

    List<Book__c> books = Trigger.new;

    BookPriceController.applyDiscount(books);
}

Написание юнит тестов

  1. Далее следует написание тестов для нашего вспомогательного класса и триггера. Однако нам достаточно написать тесты для BookTrigger, и он автоматически покроет класс BookPriceController.
    Создадим Unit Test Class, и назовём его BookPriceControllerTest. Если вы работаете через Intellij IDEA, то создавать нужно Unit Test Class.
@IsTest
private class BookPriceControllerTest {

   
}

Аннотация @IsTest указывает на то что класс тестовый.

  1. Теперь нам нужны данные на которых мы могли оттестировать работу нашего триггера, но тестировать на текущих данных нашей организации очень нежелательно, и вообще никогда так не делайте!!! Для этого у нас есть возможность создать временные данные, которые будут создаваться в базе данных SF перед каждым тестом и после удаляться. И данные на нашей организации не “пострадают”.
    Добавим метод :
    @TestSetup
    private static void setup() {
        Book__c book = new Book__c(Name = 'Behind the Cloud', Price__c = 100);

        insert book;
    } 

Рассмотри код детальнее.
@TestSetup - указывает на то что метод будет создавать данные для тестирования, что бы не пришлось менять актуальные данные в своей организации.
Book__c book = new Book__c(Name = 'Behind the Cloud', Price__c = 100); - это описание нашего объекта для тестирования, пока его ещё нет в нашей базе данных.
insert book - вставляет новую запись в базу данных.

  1. Теперь у нас есть данные с которыми мы можем работать. Потому что как я сказал ранее, метод с аннотацией @TestStup будет выполняться перед каждым тестовым методом.Выполняются они кстати хаотично.
    Добавим тестовым метод:
    @IsTest
    static void testBehavior() {
        Book__c book = [
                SELECT Price__c
                FROM Book__c
                WHERE Name = 'Behind the Cloud'
        ];

        System.assertEquals(90, book.Price__c);
    }

Рассмотри код детальнее.
@IsTest - указывает на то что это тестовый метод.

Book__c book = [
                SELECT Price__c
                FROM Book__c
                WHERE Name = 'Behind the Cloud'
        ];

Это SOQL запрос запрашивает книгу которую мы вставили в базу данных.

System.assertEquals(90, book.Price__c); - проверка данных на валидность, мы знаем что цена должна была уменьшиться с 100 до 90, что мы собственно и проверяем.

  1. Осталось запустить этот тестовый класс и получить результаты выполнения всех тестовых методов в этом классе. После вы сможете увидеть на сколько процентов покрыт ваш код.

Где же мы тестируем триггер? Всё просто, при каждой вставке в БД, которую индицирует наш метод с аннотацией @TestSetup, ведь в нём есть insert DML операция. Т.е при каждой попытке вставить запись book в БД триггер срабатывает(параметр before insert способствует этому), и меняет значение Price.

Deploy

Написание юнит тестов необходимо, не только потому что это неотъемлемая часть разработки в большинстве языков и Apex не исключение, но и потому что для деплоя кода на production необходимо что бы хотя бы 75% кода были покрыты тестами и 100% из них проходили. Более детально про деплой кода можно почитать в статье : Deploy метаданных на организацию.

4 Вподобання

поясните пожалуйста новичку,это где?

Тут имелось ввиду в той IDE (например Intellij IDEA, VSCode) или девелопер консоли, которой пользуетесь
Тут можно посмотреть:


Ошибка в аннотации @TestStup. Если возможно исправить - исправьте, пожалуйста.

Спасибо,
можно показать как созданные классы выглядят в
Developer Console полностью

I have some problem with code on 7 line … Who can hepl me with this trouble?
image