0

So I have some code below that causes the error:

System.DmlException: Insert failed. First exception on row 0; first error: MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object (or vice versa): GroupMember, original object: Submit_CI__c: []

Here is the method in question:

 @future
public static void addToPublicGroup(List<Id> uid, List<Id> gid)
{
//if(!Test.isRunningTest())
//{
    if(!uid.isEmpty())
    {
        List<GroupMember>  lstGm = new List<GroupMember>();
        for(integer j = 0; j<uid.size() ; j++)
        {
            lstGm.add(new GroupMember(UserOrGroupId = uid[j], GroupId = gid[j]));
        }        
        //if(!Test.isRunningTest())
            insert lstGm;
        utility.AddMemToPbGroup = true;
     }    
//}
 }

I have looked around and have seen you can use the following:

    System.RunAs(usr)
    {
        Test.startTest();
           myInsertMethod();
        Test.stopTest();
    }
}

However, within 'myInsertMethod()' I am not sure what to write. Can I just write 'insert 1stGm;'

@future
private static void myInsertMethod(){

//What shall I write here?
//Can I pass parameters in?

}
  • 1
    I don't understand your question but the exception is happening because the code is doing DML operation on GroupMember and another sObject in the same transaction. Source: SObjects That Cannot Be Used Together in DML Operations and Apex Transaction. – Michal Vavra Nov 26 '17 at 20:45
  • @MichalVavra So to solve this issue I want to insert GroupMember in its own transaction using System.RunAs(usr). But to do that, I am not sure what to write in 'myInsertMethod()' – M guy Nov 26 '17 at 20:51
  • I belive you don't need another method for that. Before System.runAs() create your test data. Instead of myInsertMethod() call addToPublicGroup() and pass test data as parameters. – Michal Vavra Nov 26 '17 at 21:02
  • So -- Is your issue that your testmethod fails with the exception or the underlying code under test? If the latter, you can't use system.runAs, that only works when mocking test data in testmethods. Simply using @future or a queueable will suffice to be the separate transaction. – cropredy Nov 27 '17 at 5:52
  • @cropredy the test methods fail with the error above. The method addToPublicGroup() is where the error message says it fails (on the insert). – M guy Nov 27 '17 at 13:10
3

If the underlying code under test does DML on GroupMember and DML on "normal" (i.e. non-setup) SObjects like Account or Contact, then the DML on GroupMember has to be done in a separate transaction such as @future or a queueable. Your OP indicates that GroupMember is done in a @future.

For the testmethod, if you need to pre-insert some GroupMember to test logic, you will need to do the following

System.runAs([select Id from User where Id = :UserInfo.getUserId()][0]) {
  insert GroupMember(...); // setup objects must be inserted in a separate context
}

Test.startTest();  
  new MyClass().doWork(); // code path eventually ends up calling addToPublicGroup
Test.stoptest(); // this will cause the future method to execute
System.assert(...whatever is needed...);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.