unit testing - trailhead - Cómo evitar el error MIXED_DML_OPERATION en las pruebas de Salesforce que crean usuarios
test trigger salesforce (4)
Acabo de encontrar esto en la documentación:
Otros usos de
runAs
También puede usar el método
runAs
para realizar operaciones DML mixtas en su prueba encerrando las operaciones DML dentro del bloquerunAs
. De esta manera, omite el error de DML mixto que de otro modo se devuelve al insertar o actualizar objetos de configuración junto con otros objetossObjects
. Consulte lossObjects
que no se pueden usar juntos en operaciones DML.
Así que parece que la solución alternativa RunAs
no es una solución alternativa, pero Salesforce la asume como la única forma de solucionar el problema de DML mixto.
Espero que esto ayude
A veces, en las pruebas de Salesforce es necesario crear objetos de usuario para ejecutar parte de la prueba como un tipo específico de usuario.
Sin embargo, desde la actualización de Salesforce Summer 08, los intentos de crear tanto objetos de usuario como objetos normales (como Cuentas) en la misma prueba conducen al siguiente error:
MIXED_DML_OPERATION, la operación DML en el objeto de configuración no está permitida después de haber actualizado un objeto que no es de configuración (o viceversa): Usuario, objeto original: cuenta
Tenga en cuenta que el error no se produce cuando ejecuta las pruebas desde el IDE de Eclipse / Force.com, pero sí ocurre cuando se implementa en Salesforce y luego se ejecutan las pruebas desde Salesforce.
¿Cómo reescribo mis pruebas para evitar este error?
Aquí hay un ejemplo simple de una prueba que causa el error:
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=''[email protected]'',
emailencodingkey=''UTF-8'', lastname=''Testing'',
languagelocalekey=''en_US'',
localesidkey=''en_US'', profileid = p.Id, userroleid = r.Id,
timezonesidkey=''America/Los_Angeles'',
username=''[email protected]'');
Account a = new Account(Firstname=''Terry'', Lastname=''Testperson'');
insert a;
System.runAs(u) {
a.PersonEmail = ''[email protected]'';
update a;
}
}
Este comportamiento está realmente documentado en la documentación de salesforce: http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_dml_non_mix_sobjects.htm?SearchType . Lea dónde dice "Importante: la excepción principal a esto es cuando está utilizando el método runAs en una prueba"
No hay mucha gente de Salesforce aquí todavía, supongo.
Encontré una solución, no sé por qué funciona, pero funciona.
Todas las partes de la prueba que acceden a objetos normales deben envolverse en un System.runAs que usa explícitamente al usuario actual, como esto:
User thisUser = [ select Id from User where Id = :UserInfo.getUserId() ];
System.runAs ( thisUser ) {
// put test setup code in here
}
Entonces, el ejemplo del método text_mixed_dmlbug dado en la pregunta, se convertiría en:
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=''[email protected]'',
emailencodingkey=''UTF-8'', lastname=''Testing'',
languagelocalekey=''en_US'',
localesidkey=''en_US'', profileid = p.Id, userroleid = r.Id,
timezonesidkey=''America/Los_Angeles'',
username=''[email protected]'');
a = new Account(Firstname=''Terry'', Lastname=''Testperson'');
insert a;
}
System.runAs(u) {
a.PersonEmail = ''[email protected]'';
update a;
}
}
Entonces los errores MIXED_DML_OPERATION dejan de suceder.
Parece que has encontrado una solución alternativa. Solo quería intentar aclarar por qué recibías este error.
Creo que se está encontrando con este problema (según http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_dml_non_mix_sobjects.htm ):
Objetos que no pueden usarse juntos en operaciones DML
Algunos sObjects requieren que realice operaciones DML en solo un tipo por transacción. Por ejemplo, no puede insertar una cuenta y luego insertar un usuario o un miembro del grupo en una sola transacción. Los siguientes sObjects no pueden usarse juntos en una transacción:
* Group1 * GroupMember * QueueSObject * User2 * UserRole * UserTerritory * Territory
Importante La excepción principal a esto es cuando está utilizando el método runAs en una prueba.
Además, las notas de la versión de verano 08 (ese enlace es un PDF) dicen:
En versiones anteriores, en una sola transacción que involucraba activadores, podía realizar operaciones DML en más de un tipo de sObject, por ejemplo, podría insertar una cuenta y luego insertar un usuario. A partir de Summer ''08, solo puede realizar operaciones DML en un solo tipo de sObject de la siguiente lista de sObjects.
Por ejemplo, no puede insertar una cuenta, luego insertar un usuario o actualizar un grupo, luego insertar un miembro del grupo.
- Grupo
- Miembro del grupo
- QueueSObject
- Usuario
- Rol del usuario
- UserTerritory
- Territorio
Además, User and Territory ahora admite las operaciones de inserción y actualización de DML, y UserRole ahora es compatible con las operaciones de inserción, eliminación de actualizaciones y DERT de inserción.
Las operaciones Dex de Apex no son compatibles con los siguientes sObjects:
- AccountTerritoryAssignmentRule
- AccountTerritoryAssignmentRuleItem
- UserAccountTeamMember