Как избежать ошибки MIXED_DML_OPERATION в тестах Salesforce, которые создают пользователей - PullRequest
32 голосов
/ 05 марта 2010

Иногда в тестах Salesforce необходимо создавать объекты User для запуска части теста в качестве определенного типа пользователя.

Однако после обновления Salesforce Summer 08 попытки создания объектов User и обычных объектов (таких как Accounts) в одном тесте приводят к следующей ошибке:

MIXED_DML_OPERATION, операция DML над объектом настройки не разрешена после обновления неустановочного объекта (или наоборот): пользователь, исходный объект: учетная запись

Обратите внимание, что ошибка не возникает при запуске тестов из Eclipse / Force.com IDE, но она возникает при развертывании в Salesforce, а затем при запуске тестов из Salesforce.

Как мне переписать свои тесты, чтобы избежать этой ошибки?

Вот простой пример теста, который вызывает ошибку:

static testMethod void test_mixed_dmlbug() {        
    Profile p = [select id from profile where name='(some profile)'];
    UserRole r = [Select id from userrole where name='(some role)'];
    User u = new User(alias = 'standt', email='standarduser@testorg.com', 
            emailencodingkey='UTF-8', lastname='Testing', 
            languagelocalekey='en_US', 
            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles', 
            username='standarduser@testorg.com');
    Account a = new Account(Firstname='Terry', Lastname='Testperson');
    insert a;

    System.runAs(u) {
        a.PersonEmail = 'test@madeupaddress.com';
        update a;
    }

}

Ответы [ 4 ]

40 голосов
/ 09 марта 2010

Думаю, здесь не так много людей из Salesforce.

Я нашел решение, я не знаю, почему оно работает, но оно работает.

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

User thisUser = [ select Id from User where Id = :UserInfo.getUserId() ];
System.runAs ( thisUser ) {
    // put test setup code in here
}

Итак, пример метода text_mixed_dmlbug, приведенный в вопросе, стал бы:

static testMethod void test_mixed_dmlbug() {  
    User u;
    Account a;      
    User thisUser = [ select Id from User where Id = :UserInfo.getUserId() ];
    System.runAs ( thisUser ) {
        Profile p = [select id from profile where name='(some profile)'];
        UserRole r = [Select id from userrole where name='(some role)'];
        u = new User(alias = 'standt', email='standarduser@testorg.com', 
            emailencodingkey='UTF-8', lastname='Testing', 
            languagelocalekey='en_US', 
            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
            timezonesidkey='America/Los_Angeles', 
            username='standarduser@testorg.com');
        a = new Account(Firstname='Terry', Lastname='Testperson');
        insert a;
    }
    System.runAs(u) {
        a.PersonEmail = 'test@madeupaddress.com';
        update a;
    }

}

Тогда ошибки MIXED_DML_OPERATION прекращаются.

13 голосов
/ 10 марта 2010

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

Я думаю, что вы столкнулись с этой проблемой (для http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dml_non_mix_sobjects.htm):

sОбъектов, которые нельзя использовать вместе вОперации DML

Некоторые объекты sObject требуют выполнения операций DML только с одним типом для транзакции. Например, вы не можете вставить учетную запись, а затем вставить пользователя или члена группы в одну транзакцию.используется вместе в транзакции:

* Group1
* GroupMember
* QueueSObject
* User2
* UserRole
* UserTerritory
* Territory

Внимание! Основное исключение - использование метода runAs в тесте.

Кроме того, Summer08 Примечания к выпуску (эта ссылка представляет собой PDF-файл):

В предыдущих выпусках в одной транзакции, включающей триггеры, вы могли выполнять операции DML над несколькими типами объектов sObject, дляНапример, вы можете вставить учетную запись, а затем вставить пользователя. Начиная с лета '08, вы можете выполнять операции DML только с одним типом sObject из следующихng список объектов sObjects.

Например, вы не можете вставить учетную запись, затем вставить пользователя или обновить группу, а затем вставить члена группы.

  • Group
  • GroupMember
  • QueueSObject
  • User
  • UserRole
  • UserTerritory
  • Territory

Кроме того,Пользователь и территория теперь поддерживают операции вставки и обновления DML, а UserRole теперь поддерживает операции вставки, обновления, удаления и вставки DML.

Операции DML Apex не поддерживаются для следующих объектов sObject:

  • AccountTerritoryAssignmentRule
  • AccountTerritoryAssignmentRuleItem
  • UserAccountTeamMember
7 голосов
/ 06 июля 2011

Такое поведение на самом деле задокументировано в документации по продажам: http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_dml_non_mix_sobjects.htm?SearchType. Прочитайте, где написано «Важно Основное исключение - использование метода runAs в тесте "

1 голос
/ 05 марта 2018

Только что нашел это в документации:

Другое использование runAs

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

Похоже, что обходной путь RunAs - это не обходной путь, а Salesforce считает его единственным способом решения смешанной проблемы DML.

Надеюсь, это поможет

Ссылка

...