2

How should I write test class for class that doesn't have methods, just fields and constructor? What are best practices?

public SelectOption(String value, String label) {
    this.value = value;
    this.label = label;
}

@AuraEnabled
public String label { get;set; }
@AuraEnabled
public String value { get;set; }

4 Answers 4

10

If the class didn't have a constructor and was just { get; set; } properties I would say don't write a test class at all as there is nothing that can go wrong within the class itself (and you should pickup some code coverage via other tests).

In your class you do have a constructor and missing the this is a common error so arguably you should test that constructor:

SelectOption so = new SelectOption('x', 'y');
System.assert('x', so.label);
System.assert('y', so.value);
1
  • 1
    It is also worth noting you can still essentially get code coverage for this class if it is utilized within a method that is being tested. Implicit testing isn't always ideal, but it would work in this case.
    – zgc7009
    Apr 10, 2017 at 16:00
3

If SFDC didn't require Apex coverage, I'd offer the argument that SelectOption class may be too simple to be worth bothering with. But here we go for the cheap win to keep the coverage level up.

Note, some of the below is arguably over-engineered, but I just use some boiler plate for all my tests to preempt sfdc quirks from haunting me.

@isTest
public class SelectOptionTest {
    private static final User TEST_RUNNER = TEST_RunAsUserFactory.create();
    private static final String NEW_VALUE = 'test value';
    private static final String NEW_LABEL = 'test label';

@isTest public static void constructorShouldSetProperties(){
    // Arrange
    // Nothing to do here

    // Act
    SelectOption resultOption;
    System.runAs(TEST_RUNNER){
        Test.startTest();
        {
            resultOption = new SelectOption(NEW_VALUE, NEW_LABEL);
        }
        Test.stopTest();
    }

    // Assert
    System.assertEquals(NEW_VALUE, resultOption.value);
    System.assertEquals(NEW_LABEL, resultOption.label);
}

@isTest public static void setValueShouldResetValue(){
    // Arrange
    SelectOption classUnderTest = new SelectOption('old value', 'old label');

    // Act
    System.runAs(TEST_RUNNER){
        Test.startTest();
        {
            classUnderTest.setLabel(NEW_VALUE);
        }
        Test.stopTest();
    }

    // Assert
    System.assertEquals(NEW_VALUE, classUnderTest.getValue());
}

@isTest public static void setLabelShouldResetLabel(){
    // Arrange
    SelectOption classUnderTest = new SelectOption('old value', 'old label');

    // Act
    System.runAs(TEST_RUNNER){
        Test.startTest();
        {
            classUnderTest.setLabel(NEW_LABEL);
        }
        Test.stopTest();
    }

    // Assert
    System.assertEquals(testlabel, classUnderTest.getLabel());
}
}
3

First, you should know that your getters and setters themselves are methods. Just because you're using shorthand syntax doesn't change the fact that you're implicitly creating methods.

/**
 * Convenient getter and setter method definition
 * using Apex in Salesforce
 */
public class PlainOldApexObject {
    public String name { get; set; }
}

/**
 * Java equivalent, showing what the Apex shorthand
 * is effectively doing
 */
public class PlainOldJavaObject {
    private String name;

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Second, any code you create must be used somewhere to add value to something. Otherwise the code is worthless, and you should just delete the code.

So, since your code is used somewhere to facilitate some business process, by virtue of fully testing the relevant business process, your simple class should've been covered 100% already, without you having to write any Apex tests just for the simple class.

Example: Lightning Component Model

Since you showed the @AuraEnabled annotation in your sample code, I'm assuming you're probably trying to cover an Apex model you'd created for a Lightning component or app. As with Visualforce, the most basic test here is to simulate the loading of a page/view in your Apex test.

Let's say you have the following controller, no action methods, just properties.

public class ExpenseTrackerController {

    @AuraEnabled
    public Date currentDate { get; set; }

    @AuraEnabled
    public String summary { get; set; }
}

And this controller is used to back an Expense Tracker app. In this case, you may write Apex tests as follows, which not only provides code coverage but also validates the expected use of that code in a real scenario.

/**
 * Tests to cover the controller and model behaviors supporting the Expense 
 * Tracker app (expenseTracker.app). Assume there's an Apex class backing
 * the app called ExpenseTrackerController.
 */
@isTest
private class ExpenseTrackerAppTest {

    /**
     * Test that the user is able to log an expense in the app
     */
    @isTest
    private static void userLogsExpense {

        // Initialization of the controller
        ExpenseTrackerController controller = new ExpenseTrackerController();

        // Simulate the load of the controller specifically in the context
        // of the Expense Tracker app
        loadExpenseTrackerApp(controller);

        // Start the test and enter some data
        Test.startTest();

        // Simulate data entry
        controller.currentDate = Date.today();  // invokes setter
        controller.summary = 'Apex testing Q&A';  // invokes setter

        // ...
    }

    /**
     * Utility method used by all test methods to simulate the initial loading
     * of the Expense Tracker app. When the app loads, all getters are called
     * to get the values of specific properties in the controller.
     */
    private static void loadExpenseTrackerApp(
            ExpenseTrackerController controller) {

        // Simulate the getting of specific properties, in the order that
        // they are rendered on the view.
        Date currentDate = controller.currentDate;  // invokes getter method
        String summary = controller.summary;  // invokes getter method
    }
}
2

Just Create the Object of that Class. For example, If your class name is A then:

 A objectOfA = new A();   // this will invoke the constructor.

For more details on best practice and for getting started with test class please refer to: Write at Test Class for a really simple class

0

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.