I’m in a situation where I have to use a future method to avoid MIXED_DML_OPERATION error. I have a trigger that runs after INSERT on USER and creates a custom object X. They are in 1:1 relation. User is an owner of X and sharing model is private.
I’m not sure what is the best approach to write tests for this scenario. I want to keep my data isolated so in tests I need to create a User and X he owns. I can think of 2 scenarios:
1) Create a mock user and let the trigger create X for the test
Because in test context @future methods are executed when the Test.stopTest() is called I would have to enclose my set up section in Test.start/stopTest(). This means I can’t use these two later in the method where I want to test a particular logic on X.
2) Create a mock user, don't wait for future method and create X manually in mock section
I can write a single test for creation of X in the trigger. In all other tests checking the business logic on X I create a user, manually create X setting the user as the owner. The problem is that now if later in the method I call Test.start/stopTest() and do a select from X where ownerId = user.id I will get two X records.
To my surprise I discovered that I’m able to insert X objects from the trigger while running a test. I didn't use the @future method and I got no MIXED_DML_OPERATION error ( - a bug?).
for(User aUser: newUsers) {
newXtoInsertFromFuture.put(aUser.ID, aUser.lastName )
objectX.add(new X(ownerID=aUser.id, property=aUser.lastName));
}
if(Test.isRunningTest()) {
insert objectX;
} else {
matchUsersWithX(newXtoInsertFromFuture);
}
With this code in trigger I can create a user in a test set up section and the corresponding X is created synchronously. I’m not sure why things work this way. Anyway this looks like a dirty hack that yields the same problems as 2) if I ever call Test.start/stopTest() in the test.
Could any of you good people out there tell me what is the correct way to write tests in my case? thanks in advance.