3

I'm running into an odd issue with some of my unit tests & can't seem to find out what exactly is causing it the problem.

Several of my unit tests revolve around converting a lead to an account (I'm using person accounts in case that makes a difference, but I don't think that's related to the problem). On the account object, I have several validation rules that check a field in a hierarchy custom setting + the values of some fields on the account. Here's an example of one of my validation rules

AND(
 $Setup.ObjectSettings__c.AccountRequireOneContactMethod__c
 ,IsPersonAccount=true
 ,AND(
   ISBLANK(PersonEmail)
   ,ISBLANK(PrimaryAddress__c)
   ,ISBLANK(PrimaryPhone__c)
   ,ISBLANK(SecondaryPhone__c)
 )
)

ObjectSettings__c is the custom setting object that lets me easily toggle different validation rules, apex code, etc. The validation rules work fine for unit tests that focus an the account object - I even have some tests that specifically test to make sure that the validation rules are throwing an error when expected.

The problem I'm running into is when I convert a lead to an account in a unit test, the account validation rules throw a System.DmlException (example below). Everything works fine when I manually run through the same steps that the unit test is taking, so this is only an issue for tests. Removing the reference to the custom setting in the validation rule appears to fix the issue, but I don't want to remove it just to get these tests working.

System.DmlException: ConvertLead failed. First exception on row 0; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Validation error on Account: Validation Formula "One_contact_method_required" Invalid (null): []

I know that the custom setting exists in my tests - the first line of my unit tests creates the custom setting, and I even added some assert statements to make sure the custom setting exists with the correct values and used System.debug() to show the custom setting in the logs and I can see that it's there. But something about converting a lead in a unit test with these account validation rules causes the tests to fail.

Last detail: on the lead settings, I have the option "Lead Conversion Settings --> Require Validation for Converted Lead" set to true so that the 'before' triggers & validation rules fire on the new account/opportunity. This is something that I do not want to disable: our triggers handle setting a lot of account fields and we want to ensure that the validation rules are applied.

Any suggestions or ideas? Here is one of the methods that fails.

static testMethod void convertLeadToAccount() {
    ObjectSettings__c objectSettings = ObjectSettings__c.getInstance();
    upsert objectSettings;

    Lead lead = new Lead(
        FirstName = 'Test'
        ,LastName = 'Lead'
        ,PrimaryPhone__c = '9015551234'
    );
    insert lead;

    Lead insertedLead = [SELECT Id, IsConverted FROM Lead WHERE Id = :lead.Id];
    System.assert(!insertedLead.IsConverted);

    Test.startTest();

    Database.LeadConvert leadConvert = new Database.LeadConvert();
    leadConvert.setLeadId(lead.Id);
    leadConvert.setConvertedStatus('Qualified');

    Database.LeadConvertResult leadConvertResult = Database.convertLead(leadConvert);
    System.assert(leadConvertResult.isSuccess());

    Test.stopTest();
}
  • Do you have seeAllData = "true" set in your test class? I'm guessing not. In any case, it would probably be helpful if you posted one of your test classes for us to look at. – crmprogdev Mar 27 '15 at 18:50
  • crmprogdev, no, I do not have seeAllData = "true" in any of my test classes. I've added one of the test methods to my original post - it's a very basic method that just converts a lead to an account. – jongpie Mar 27 '15 at 18:59
  • 1
    ObjectSettings__c objectSettings = ObjectSettings__c.getInstance(); upsert objectSettings; is odd as there is no mocked value for ObjectSettings__c – cropredy Mar 27 '15 at 20:00
  • It definitely works though - I use this to create the custom settings with the default settings (most of the fields on the setting are booleans, so it creates the setting with the fields set to true or false, depending on how I configured the field). And it's very odd that this works perfectly fine in some of my other tests, but when I try to convert a lead, it starts complaining. – jongpie Mar 30 '15 at 14:01
  • Hi jongpie, did you solve this problem in the meantime? I have the same experience and the answers below are not working for me. – georg w. Aug 3 '15 at 14:45
0

Set AccountRequireOneContactMethod__c to true or false (depending on how you're testing). Since the setting "doesn't exist" because of isolation, you need to specify a value for the checkbox, or it will end up null. While this is probably a bug, I have seen it before, and the only way to fix it is to be explicit about the setting value. In fact, I'd construct it manually and specify the SetupOwnerId:

ObjectSettings__c objectSettings = new ObjectSettings__c(AccountRequireOneContactMethod__c = true, SetupOwnerId=UserInfo.getOrganizationId());
insert objectSettings;
  • That unfortunately does not fix the issue. Using my method still sets the values because they're boolean fields with default values (and if I throw in a system.debug method in the test, I can see that the custom setting is created with the values I want), but even when I use your method, it still gives me the same error. – jongpie Mar 27 '15 at 19:39
  • @jongpie That's incredibly interesting. I'd log a case with support and see what they say, then. It definitely sounds like a bug of some sort. Out of curiosity, what if you change SetupOwnerId to UserInfo.getUserId()? – sfdcfox Mar 27 '15 at 19:51
  • I will definitely lost a case with support, but I have a feeling that they won't help since we don't have premier support - when I've had other issues, they've basically said they can't help me unless I buy premier support. And I tried using UserInfo.getUserId() for SetupOwnerId, but it still gives me the same issue. – jongpie Mar 30 '15 at 14:03
0

The workaround that can be used in this case is to use System.RunAs() when running the Lead Conversion Logic.

If you are using SeeAllData as False, then you can create a new User record in the same transaction and then execute the Lead Conversion Logic in that User's Context.

0

Can you try this ?

static testMethod void convertLeadToAccount() {   
  Id Profile_id = [SELECT Id FROM Profile WHERE Name = 'System Administrator'].Id;
  User u = [select Id from User where ProfileId =: Profile_id];
  ObjectSettings__c objectSettings = ObjectSettings__c.getInstance();
  upsert objectSettings;
  Lead lead = new Lead(
        FirstName = 'Test'
        ,LastName = 'Lead'
        ,PrimaryPhone__c = '9015551234'
   );
  insert lead;
  Lead insertedLead = [SELECT Id, IsConverted FROM Lead WHERE Id = :lead.Id];
  System.assert(!insertedLead.IsConverted);
  Test.startTest();
  system.RunAs(u){
     Database.LeadConvert leadConvert = new Database.LeadConvert();
     leadConvert.setLeadId(lead.Id);
     leadConvert.setConvertedStatus('Qualified');
     Database.LeadConvertResult leadConvertResult = 
     Database.convertLead(leadConvert);
     System.assert(leadConvertResult.isSuccess());
  }
  Test.stopTest();
}
  • Unfortunately that doesn't work either - I still get the same errors regarding the validation rules. – jongpie Aug 6 '15 at 18:15
-3

If SeeAllData isn't set, you either need to set that on the Test classes or create all of the Custom Settings through code.

I would highly recommend you don't turn SeeAllData on and instead create the custom settings in code.

Pro tip: create a Test Helper class that can create the necessary custom settings.

  • I am creating the custom settings through code (I agree with not using SeeAllData) and in several places have asserts to make sure the settings exist with the values I expect. I'm actually using a helper class for creating/setting the custom settings, but for the sake of keeping my sample method smaller, I've simplified some of it. – jongpie Mar 27 '15 at 20:26

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.