+ Start a Discussion
ClaiborneClaiborne 

Different Test Class Behavior in Summer '13 Release

I have a custom object that is created to mirror the Product object whenever a new Product record is created. It fires via a trigger on the Product object.

 

In the Spring '13 release, with seeAllData=true, the mirror object is created without problem. With seeAllData=false, the mirror object is not created, I guess because the trigger is outside of the test space.

 

In the Summer '13 release, the mirror object is not created. Tests that used to work now fail because the mirror object does not exist.

 

I have a lot of tests that depend on this behavior. 

 

Is this a bug or a new feature?

GSBassoGSBasso

Hi,

 

Your trigger should fire regardless of what you are testing.

 

SeeAllData only affects whether your test can see existing data (test class must be API 24.0 or newer).

 

Ideally your tests would not rely on existing data and therefore should be able to function with SeeAllData false (regardless of their API) but sometimes the nature of what you are testing requires that you have access to existing data.

 

ClaiborneClaiborne
Yes, everything you say is the way it is supposed to work.

But it does not work that way.

Same test - fails in Summer '13, data not created by trigger. Works in
Spring '13, data created by trigger.

--
David Claiborne | Principal | (504) 655-0000 | www.claico.com
GSBassoGSBasso

In that case I'd open a case with Salesforce and let them figure it out.

 

(We do the same if it's a clear cut case where the test used to work but now fails after the platform upgrade).

ClaiborneClaiborne
A case is open, and Developer Support has already contacted me.

I will post a response here when I get an answer

--
David Claiborne | Principal | (504) 655-0000 | www.claico.com
ClaiborneClaiborne

OK, here is the code that is causing the problem.

 

// Create service product. This automatically
// creates product reference record.
Product2 sp = new product2(
name='Sales Product 1',
description='Test Service Item',
Quote_Category__c = 'Cyan Engineering and Installation Services');
insert sp;

// Retrieve Product Reference record
gii__Product2Add__c pr = [
select id
from gii__Product2Add__c
where gii__ProductReference__c = : sp.id
limit 1];
pr.gii__service__c = true;
update pr;

 

When this code runs on Summer '13, it fails because pr does not return any records.

 

I also tried this:

 

// Retrieve Product Reference record
List<gii__Product2Add__c> prlist = [
select id
from gii__Product2Add__c
where gii__ProductReference__c = : sp.id];
gii__Product2Add__c pr = prList[0];
pr.gii__service__c = true;
update pr;

 

This fails because prList has no records.


So I commented the retrieve out, and tried to create the record using the code below.

 

/* - Removed because of bug in Summer '13 releasse
// Retrieve Product Reference record
gii__Product2Add__c pr = [
select id
from gii__Product2Add__c
where gii__ProductReference__c = : sp.id
limit 1];
pr.gii__service__c = true;
update pr;
*/
// Create Product Reference record
gii__Product2Add__c pr = new gii__Product2Add__c(
Name = sp.Name,
gii__ProductReference__c = sp.id,
gii__Service__c = true);
insert pr;

 

This produced the error:

 

System.DmlException: Insert failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Cannot add new Product reference, already exists for this Product: [gii__ProductReference__c]

 

So the record is getting created. What has changed in Summer '13?

 

In desparation, I tried moving the retrieve code farther down in the test method, after several more inserts.

 

Eureka ! It worked.

 

But this is still wrong.

 

If there is a trigger that fires after a record is inserted, control should not return to the calling method until all actions in the trigger complete, even if the trigger is an after insert.

 

And this still works as originally coded in Spring '13.

GSBassoGSBasso

Your findings suggest that somehow the creation of the reference record is deferred/delayed, but you are quite correct that all triggers should have completed by the time the insert returns.

 

Is this working as expected when creating a Product through the UI (or even Data Loader)? I'm wondering if the behaviour only occurs when running tests? Does the setting for SeeAllData make any difference?

 

I'd suggest putting an System.assert(sp.Id != null) statement right after your insert. In my tests I always verify that records were created as expected.

 

I'd also add an assert that verifies that the reference record is created as expected. This is more a matter of style because you are effectively doing that anyways by querying for the record (so either the query fails or the assert fails).

 

I'm assuming the trigger is part of the gii namespace as well. For fun (!?) what happens if you have a trigger that isn't part of any namespace? I'm obviously grasping at straws here...

 

ClaiborneClaiborne
Thanks for the suggestions.

It is definitely a timing issue, and it only occurs in Summer '13. The test
code has been working for the previous three releases.

All of the records are being created, just slower than I expected.

I will try putting in the system.assert(sp.id != null). If nothing else,
this should slow things down enough for the following query to work.

I cannot just create the followup record because there is validation code
in the gii package that prevents multiple mirror records. So when I try an
insert, it fails because the record - that I can't find via a query -
already exists. Catch 22.

--
David Claiborne | Principal | (504) 655-0000 | www.claico.com