function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
tjm_pacstratstjm_pacstrats 

Trigger and Test Class work in Sandbox but Fail when uploading into Production

I just started using Eclipse to write and promote Triggers/Classes and for some reason the following Trigger and Test Class both work in the Sandbox (with 100% coverage) but fail in Eclipse.  

 

In short, the Trigger updates the X1st_Campaign__c field with the Id of the most recent Campaign that the Lead responded to.

 

Trigger

 

trigger Set1stCampaign on Lead (before update)

{

for (Lead l : System.Trigger.new)

{

List<CampaignMember> campaign = new List<CampaignMember>();

campaign = [select CampaignId from CampaignMember where LeadId = :l.Id AND HasResponded = True order by FirstRespondedDate Desc limit 1];

if(campaign.size()>0)

{

l.X1st_Campaign__c = campaign[0].CampaignId;

}

}

}

 

Test Class

 

public class Lead1stCampaignTestClass {

static testMethod void OppOwnerRoleTest ()

{

Lead l = new Lead (FirstName='Test', LastName='Leadxx11xx11', Company='Testing Company', Industry='BioPharma', Sub_Industry__c='Big Pharma', LeadSource='Web', Status='Open');

insert l;

 

Campaign c1 = new Campaign (Name='Test Campaign 1', CurrencyIsoCode='USD', IsActive=True, Status='In Progress');

insert c1;

 

Campaign c2 = new Campaign (Name='Test Campaign 2', CurrencyIsoCode='USD', IsActive=True, Status='In Progress');

insert c2;

 

CampaignMember cm1 = new CampaignMember (CampaignId=c1.id, LeadId=l.id, Status='Responded');

insert cm1;

 

CampaignMember cm2 = new CampaignMember (CampaignId=c2.id, LeadId=l.id, Status='Responded');

insert cm2;

 

update l;

System.assertEquals(c1.id, [select X1st_Campaign__c from Lead where LastName='Leadxx11xx11'].X1st_Campaign__c);

 

}

}

 

Here are the errors from Eclipse:

System.Exception: Assertion failed: Expected: [id is listed], Actual null

Test coverage of selected Apex Trigger is 0%, at least 1% test coverage is required

 

I would appear that the Campaigns aren't being associated with the Lead so maybe I'm missing something there.

 

 

Any help or suggestions would be appreciated.

 

Message Edited by tjm_pacstrats on 02-21-2009 07:04 PM
Message Edited by tjm_pacstrats on 02-21-2009 07:05 PM
Message Edited by tjm_pacstrats on 02-21-2009 07:06 PM
Best Answer chosen by Admin (Salesforce Developers) 
JonPJonP

Re: X1st_Campaign__c isn't a field on Lead.

That's not what I'm saying.  X1st_Campaign__c is a field on Lead, not on List.  SOQL queries return an object of type List unless you include the expression "LIMIT 1", in which case they return a single object instance (or null if there's no result).

For example:

 

 

List<Lead> leadsList = [SELECT Id, Name FROM Lead]; if (leadsList.isEmpty()) { // no query results were returned, but you still get an empty List object } Lead singleLead = [SELECT Id, Name FROM Lead LIMIT 1]; if (singleLead==null) { // no query results were returned }

Now it may be (I'm really not sure) that everything works fine if you assign the query results to a singular SObject variable as long as the query returns a single record at runtime.  But as soon as the query returns two or more rows, you'll get an exception.  The "LIMIT 1" clause prevents this under all circumstances.

Now, this all may be unrelated to the problems you're seeing but you might as well fix it before you put your code into production.

 

 

All Answers

JonPJonP

I'm surprised your tests passed in Sandbox.  Your assert statement should be failing, because the List<Lead> result from the SELECT statement does not have a field "X1st_Campaign__c".

 

Try this:

 

System.assertEquals(c1.id, [select X1st_Campaign__c from Lead where LastName='Leadxx11xx11' LIMIT 1].X1st_Campaign__c);

 

The "LIMIT 1" clause forces the query result to be a Lead rather than a List<Lead>.

 

Also, some tips to fix your trigger:

1. There is no reason to instantiate an empty List<CampaignMember> when it gets replaced in the next line.  You can just say:

 

List<CampaignMember> campaign = [select CampaignId from CampaignMember where LeadId = :l.Id AND HasResponded = True order by FirstRespondedDate Desc limit 1];

 

2. Since you are querying a specific CampaignMember, using the LIMIT 1 clause here (as you did) makes sense.  But then your code should look like this:

CampaignMember campaign = [select CampaignId from CampaignMember where LeadId = :l.Id AND HasResponded = True order by FirstRespondedDate Desc limit 1]; if(campaign != null) { l.X1st_Campaign__c = campaign.CampaignId; }

3. Never put a query inside a loop.  Write a test that updates a batch of 200 Leads, and get it to pass without failing on Apex governor limits, and you'll be good to go.

 

 


 

 

tjm_pacstratstjm_pacstrats

Unfortunately, neither of those tricks worked.  I'm still getting the test coverage and expected results errors.  I didn't quite understand what you meant by X1st_Campaign__c isn't a field within Lead.  This is a custom field within in the Object.  

 

I've used the same general layout of the trigger and class before and I haven't had any issues in Prod or Sandbox so I'm puzzled why this is now an issue.  The trigger defintely works as I've tested it a dozen times in Sandbox, so I'm thinking the issue centers around the test class.  But again, I get 100% coverage in Sandbox but an error when I try to promote to Prod.

BritishBoyinDCBritishBoyinDC

I would do a system.debug on each insert to check that each object is being inserted as I'm wondering if any of the test data happens to exist in the sandbox already? I've had that happen - the sandbox actually has a record in it that I thought I was creating, so it isn't actually referring to the test record you're creating, so you don't realize the test record creation is failing - but since it isn't there in prod, it only ends up failing when you deploy it...

JonPJonP

Re: X1st_Campaign__c isn't a field on Lead.

That's not what I'm saying.  X1st_Campaign__c is a field on Lead, not on List.  SOQL queries return an object of type List unless you include the expression "LIMIT 1", in which case they return a single object instance (or null if there's no result).

For example:

 

 

List<Lead> leadsList = [SELECT Id, Name FROM Lead]; if (leadsList.isEmpty()) { // no query results were returned, but you still get an empty List object } Lead singleLead = [SELECT Id, Name FROM Lead LIMIT 1]; if (singleLead==null) { // no query results were returned }

Now it may be (I'm really not sure) that everything works fine if you assign the query results to a singular SObject variable as long as the query returns a single record at runtime.  But as soon as the query returns two or more rows, you'll get an exception.  The "LIMIT 1" clause prevents this under all circumstances.

Now, this all may be unrelated to the problems you're seeing but you might as well fix it before you put your code into production.

 

 

This was selected as the best answer
tjm_pacstratstjm_pacstrats

Well, I updated the test class to include limit 1 on all queries and re-tooled my test class to look for a very unique Lead and everything deployed to Production with 100% coverage and no issues.  Thanks for everyone's help.