Доступ к значению Trigger.New в тестовом классе Apex
tl; dr - Как заставить тестовый класс подождать, пока не будет выполнен определенный триггер с его обновлениями или вставками, прежде чем продолжить тест?
Фон
У меня есть триггер, который создает новый Portal_Content__c
объект каждый раз, когда создается объект Account, а затем связывает обе записи друг с другом (см. Trigger Account ниже).
Я также создал триггер на Portal_Content__c
объект, который срабатывает при удалении записи. При удалении триггер ищет соответствующие Account
запишите и удалите его (см. раздел "Триггер содержимого портала" ниже).
Мой вопрос касается моего класса тестирования содержания портала (окончательный блок кода ниже). Когда я запускаю вставку DML для записи учетной записи, триггер учетной записи должен заполнить a.Portal_Content_Record__c
поле с записью содержимого портала, созданной в триггере учетной записи. Тем не менее, когда я побежал мой system.debug()
тесты показали, что a.Portal_Content_Record__c
поле является пустым при выполнении запроса SOQL. Мне удалось обойти это, выполнив поиск записи контента портала по совпадению по названию, но я хотел бы сделать скрипт более надежным, выполнив поиск по точному идентификатору.
Вопрос
Как заставить класс тестирования контента портала подождать, пока триггер учетной записи не заполнит a.Portal_Content_Record__c
поле, прежде чем двигаться дальше с тестом?
- Кодовые блоки--
Триггер аккаунта
trigger AccountHandler on Account (before insert, after insert, after update, after delete) {
List<Account> alist = Trigger.New;
List<Account> oldlist = Trigger.Old;
// Create new Portal Content with same name as Account if Account is record type 'College/University,'
// then assign newly created Portal Content to 'Portal Content Record' lookup field on new Account
if(Trigger.isBefore && Trigger.isInsert){
for(Account a : alist) {
if (a.RecordTypeId == '012i0000001Iy1H') {
Portal_Content__c p = new Portal_Content__c(
Name=a.Name,
RecordTypeId='012i0000001J1zZ'
);
insert p;
a.Portal_Content_Record__c = p.Id;
}
}
}
// Delete Portal Content record referenced in an Account's 'Portal Content Record' lookup field
// if the Account is deleted
if (Trigger.isAfter && Trigger.isDelete){
for(Account a : oldlist){
for(Portal_Content__c p : [SELECT ID FROM Portal_Content__c WHERE ID = :a.Portal_Content_Record__c]){
delete p;
}
}
}
// After the new Portal Content record has been created, assign the Account ID of the Account that created it
// to the 'School SFDC ID' field on the new Portal Content record.
if (Trigger.isAfter && Trigger.isInsert){
for(Account a : alist){
List<Portal_Content__c> plist = [SELECT ID FROM Portal_Content__c WHERE Id = :a.Portal_Content_Record__c];
for(Portal_Content__c p : plist){
p.School_SFDC_ID__c = a.Id;
update p;
}
}
}
// Prevent more than one Account from being assigned to a single Portal Content record
if (Trigger.isAfter && Trigger.isUpdate) {
for(Account a : alist){
if (a.Portal_Content_Record__c != null){
List<Account> alist = [SELECT ID FROM Account WHERE Portal_Content_Record__c = :a.Portal_Content_Record__c];
system.debug('alist: ' + alist);
if (alist.size() > 1) {
a.addError('The Portal Content record you selected is already associated with another School. Please select a different Portal Content record');
}
}
}
}
}
Триггер содержимого портала
trigger PortalContentHandler on Portal_Content__c (before insert, after update, after insert, after delete) {
// If Portal Content is deleted and Account is tied to Account record, delete Account record
if(Trigger.isAfter && Trigger.isDelete){
List<Portal_Content__c> plist = Trigger.old;
for(Portal_Content__c p : plist) {
List<Account> alist = [SELECT ID FROM Account WHERE Id = :p.School_SFDC_ID__c];
for(Account a : alist){
delete a;
}
}
}
// If more than one Portal Content with the same name, prevent new Portal Content record from being created
else if(Trigger.isAfter && (Trigger.isUpdate || Trigger.isInsert)){
List<Portal_Content__c> plist = Trigger.New;
for(Portal_Content__c p : plist){
List<Portal_Content__c> pquery = [SELECT ID FROM Portal_Content__c WHERE Name = :p.Name];
if(pquery.size() > 1){
p.addError('There is already a Portal Content record with this name. Please select a different name.');
}
}
}
}
Класс тестирования портала
@isTest
public class PortalContentHandlerTest {
@isTest static void createThenDeletePortalContent(){
Account a = new Account(Name='deletePortalTest',RecordTypeId='012i0000001Iy1H');
insert a;
List<Portal_Content__c> plist = [SELECT ID FROM Portal_Content__c WHERE Name = :a.Name];//Id = :a.Portal_Content_Record__c];
system.debug('Delete Info: a.Id = ' + a.Id + ', Portal_Content_Record = ' + a.Portal_Content_Record__c+ ', plist = ' + plist);
for(Portal_Content__c p : plist){
delete p;
}
system.debug('Delete Info: a.Id = ' + a.Id);
List<Account> checklist = [SELECT ID FROM Account WHERE Id = :a.Id];
system.debug(checklist);
system.assertEquals(0, checklist.size());
}
1 ответ
Я проверил это в моей организации. Пожалуйста, найдите мои комментарии ниже.
Согласно вашему требованию, у меня есть триггер, который создает новый объект Portal_Content__c при каждом создании объекта Account, а затем связывает обе записи друг с другом (см. Ниже Trigger Account).
Я вижу, что есть отношения наAccount(Portal_Content_Record__c )
иPortal Content (School_SFDC_ID__c)
, Вы устанавливаетеPortal_Content_Record__c
, но вам нужно связатьSchool_SFDC_ID__c
а также выполнить ваше требование. Пожалуйста, найдите ниже кодtrigger AccountHandler on Account (before insert, after insert, after update, after delete) { List<Account> alist = Trigger.New; List<Account> oldlist = Trigger.Old; // Create the new Portal Content with the same name as Account if Account is record type College/University, // then assign newly created Portal Content to Portal Content Record lookup field on new Account if(Trigger.isBefore && Trigger.isInsert){ for(Account a : alist) { if (a.RecordTypeId == '012i0000001Iy1H') { Portal_Content__c p = new Portal_Content__c( Name=a.Name, RecordTypeId='012i0000001J1zZ', School_SFDC_ID__c = a.id ); insert p; a.Portal_Content_Record__c = p.Id; } } } }
Я вижу, единственное, что
delete
не покрываетсяPortalContentHandler
потому что это не соответствует условию дляList<Account> alist = [SELECT ID FROM Account WHERE Id = :p.School_SFDC_ID__c];
Заполните его при создании Контента портала, как описано выше.Кроме того, вам нужно изменить свой тестовый класс, поскольку нет данных для контента портала, который вы пытаетесь запросить. В тестовом классе вы получаете только те данные, которые вы там создали. Тот, который создается AccountHandler, не будет частью вашего тестового класса. Создайте те же данные, что и в триггере.
@isTest public class PortalContentHandlerTest { @isTest static void createThenDeletePortalContent(){ Account a = new Account(Name='deletePortalTest',RecordTypeId__c='012i0000001Iy1H'); insert a; Portal_Content__c p = new Portal_Content__c( Name=a.Name, RecordTypeId__c='012i0000001J1zZ', School_SFDC_ID__c = a.id ); insert p; delete p; } }