0

In my apex class, I have a query on the Survey record like below. And I am using it to create a SurveyInvitation record.

Survey sr = [Select id from Survey where name='ABC'];

In my test class, this Survey record is not accessible. I am not creating the Survey record in the test class because it doesn't support any DML operation. But it should automatically fetch the survey record when I am trying to cover my apex method. I am getting an error for this soql 'System.NullPointerException: Attempt to de-reference a null object'. Can anyone please help me here? Thanks in advance.

1 Answer 1

1

This may be one of the few situations where it's appropriate to use seeAllData=true

Before you resort to that though, you should consider making a query "selector" class instead of performing a query directly in the code being tested.

Something like

public with sharing class SurveyQuerySelector{
    // Have a static collection of data that you can set in a test
    //   (and later return when the code being tested requests it)
    public static List<Survey> testData = new List<Survey>();

    public List<Survey> query(String surveyName){
        List<Survey> results = [SELECT Id FROM Survey WHERE Name = :surveyName];

        if(Test.isRunningTest()){
            results = SurveyQuerySelector.testData;
        }

        return results;
    }
}

That will allow you to set up specific data to use in your test (and only in the test) without the need for any DML.

In your test method, you'd set things up like so

// Note that we're NOT using seeAllData=true
@isTest
static void testMyMethod(){
    Survey testSurvey = new Survey(
        Id = Schema.SObjectType.Survey.getKeyPrefix() + ''.leftPad(12, 0),
        Name = 'My Survey'
    );

    SurveyQuerySelector.testData.add(testSurvey);

    // After this, your test should be basically identical to any test 
    //   you already have
}

You could also use a similar approach (minus the static list bits) and make use of the StubProvider interface. At any rate, the name of the game here is to introduce a layer in between the client code (which currently uses SOQL to query for a Survey) and the thing that you don't have control over (inserting a Survey so you can later query it) so that you can have some control over it.

6
  • N.B. i would call it a selector class rather than a service class per Lightning Enterprise Architecture convention
    – cropredy
    Commented Aug 12, 2021 at 19:03
  • My test class has a predefined testsetup method. So seeAllData=true is not supported.
    – Sam
    Commented Aug 12, 2021 at 19:05
  • @cropredy I went ahead and changed that while I was already editing to add a secondary (but similar) approach of using a StubProvider.
    – Derek F
    Commented Aug 12, 2021 at 19:06
  • @Sam Introducing a selector class as I'm suggesting is a way to avoid seeAllData=true (and I count pretty much any solution that avoids seeAllData=true as a good solution).
    – Derek F
    Commented Aug 12, 2021 at 19:08
  • @DerekF when we do Survey testSurvey = new Survey, getting compile-time error Invalid type: Survey. So the system doesn't let us create an instance of Survey.
    – Sam
    Commented Aug 12, 2021 at 19:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .