2

I am attempting to set up tests for my APEX classes, more specifically, I am attempting to create a parent class that includes a prepareDatabase function that creates data for my tests, and this function sets up some variables that I would like to use in the child classes. However, when I extend the parent class, I have no way of accessing those variables.

Here is my parent class:

public abstract class test_BaseTestController {

    static String genderMaleId = '';
    static String genderFemaleId = '';

    static public void prepareDatabase() {
        // Set Up Genders
        Gender__c maleGender = new Gender__c();
        maleGender.Name = 'Male';
        insert maleGender;
        Gender__c femaleGender = new Gender__c();
        femaleGender.Name = 'Female';
        insert femaleGender;

        List<Gender__c> genderRecs = [SELECT id, Name FROM Gender__c];
        for (Gender__c rec : genderRecs) {
            System.debug(rec);
            if (rec.Name == 'Male') { genderMaleId = rec.Id; }
            else if (rec.Name == 'Female') { genderFemaleId = rec.Id; }
        }
    }
}

And here is my child class:

@isTest
public class test_YTPStudentRolesController extends test_BaseTestController {

    /**
     * SET UP
     */
    @testSetup
    static void setup() {
        prepareDatabase();
    }

    @isTest
    static void put_updateStudentRoleRelationships() {
        System.debug(genderFemaleId);
        System.debug(this.genderMaleId);
    }
}

Now in the child class, I get errors on the two lines in the test where I am trying to debug the two variables. For the System.debug(genderFemaleId); line, I get the error: Variable does not exist and for the System.debug(this.genderMaleId); line, I get the error This cannot be referenced in a static context.

Is it possible to access these variables, or is this just another random restriction you can't get around?

3

Couple of issues here:

  • The variable declaration in parent class is private (by default), so you need to extend the visbility.
  • The variables are declared as static and thus you won't be able to access it using this keyword. this always is associated to the instance of the class. To be able to access the variables from the child class, you can just use test_BaseTestController.genderMaleId (as long as the variable is visible)

Additional note - Static variables or methods are not inherited. They are always associated with the class declaring those. You can use any static variable or method in any class as long as those are visible.

  • When I attempted to output test_BaseTestController.genderMaleId in the child class, it returned empty because it was attempting to use a different instance of the test_BaseTestController than the one the class extends... – BlondeSwan Jan 24 at 22:55
  • Because at least as in your current code, it’s initialized with an empty string. – Jayant Das Jan 24 at 22:57
  • but in the prepareForData method I set those values. After I set them, I Log them (in the parent) and they are not empty. But when I Log them in the child, they are empty. – BlondeSwan Jan 24 at 23:06
  • Whatever value you set in any method is applicable only in that transaction boundary. The time you access it from outside the class in a different transaction, you will always get the value that the variable consists of (empty in this case). In your case from child class, you are setting the values in one method (one transaction) and trying to fetch the value in another method (another transaction). Take a look at the documentation for details on this topic. – Jayant Das Jan 24 at 23:59
  • Okay, so basically Inheritance isn't a good option and I'd be better off going with a composition model? – BlondeSwan Jan 25 at 0:20
1

Variables are, by default, private. Private means "cannot be accessed outside the class." In order to access the variables in a child class, they need to be defined as "protected" or greater.

protected String genderMaleId = '';

You can read more about the access modifiers for more information.

Note: You can't make static variables protected, so you'd have to do some extra work to get this working. In your specific use case, you'd make the variable @TestVisible.

@testVisible static String genderMaleId = '';

...

System.debug(test_BaseTestController.genderMaleId);
  • When applying the protected definition, I get the errors protected fields cannot be static... But then you can't access a non-static variable in a static class, and you have to declare test methods as static... – BlondeSwan Jan 24 at 17:53
  • 1
    You cannot actually have a protected modifier on a static variable. [You can only use this (protected) access modifier for instance methods and member variables.] – Jayant Das Jan 24 at 17:57
  • @JayantDas Doh, totally forgot about that. I don't use child classes as often as I probably should. – sfdcfox Jan 24 at 18:38
  • @sfdcfox This was a very minor thing to miss for sure :). There are not lot many use cases in day to day implementations to actually use child classes that often, unless you are building a framework from scratch. – Jayant Das Jan 24 at 18:42

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.