When is it appropriate to use the @TestVisible Annotation

So from the docs I understand that @TestVisible is used to allow Unit Tests access to private and protected methods.

What I was wondering is, when is it appropriate to use this annotation?

For example, I have a list generated in a wrapper class that allows selection and processing of Users as below:

public class uUser {
    public User user {
      get;
      set;
    }

    public Boolean selected {
      get;
      set;
    }

    public uUser(User u) {
      user = u;
      selected = false;
    }
  }

I then used the following Apex to select all or deselect all these Users:

private Boolean isAllUsersSelected {
  get {
    if (isAllUsersSelected == null) {
      isAllUsersSelected = false;
    }

    return isAllUsersSelected;
  }
  set;
}

public PageReference selectAllUsers() {
  if (isAllUsersSelected == false) {
    isAllUsersSelected = true;

    for (uUser user : userList) {
      user.selected = true;
    }
  }
  else {
    isAllUsersSelected = false;

    for (uUser user : userList) {
      user.selected = false;
    }
  }

  return null;
}

Because this depends a lot on whether the isAllUsersSelected variable is true or false, I wondered whether or not it is a good idea and appropriate to use a @TestVisible method, given its access modifier is private?

Answer

I think the question in your title is too broad and opinion based to touch on here. I have worked with many developers who feel the @TestVisible annotation should never be used, but regardless, I have found some instances where it felt like the best option. For me, it boils down to using it only when I need to be able to control application behavior but want to avoid checking Test.isRunningTest().

For your use case, let’s take a moment to think about the behavior you actually care about. You want the function to toggle the selection of all of your users (I would rename it from select to toggle to reflect that purpose). So what you really care about is not this Boolean flag at all, but rather your collection of wrapper instances. That is what you should be asserting against. Make sure its size hasn’t changed, and that the individual selections are correct.

Then again, if you take a step back and look at what you are trying to accomplish, do you really need to involve the server at all for this mechanism? It may be worth looking at how you can move the functionality wholesale to the client side, since it is not exactly complex logic where unit tests offer significant advantages over acceptance tests run by end users.


(Just an aside to show the one time I do find @TestVisible perfectly acceptable)

When writing trigger handlers, it is useful to use a static flag to turn the functionality off when running certain tests to reduce the cost of DML Operations on that object. Granted, there are other strategies you can employ to reduce or remove the need to perform DML in the first place. But sometimes you can’t, and making trigger execution cheaper to run can dramatically simplify/quicken your test suite.

public with sharing class MyTriggerHandler
{
    @TestVisible static Boolean bypassTrigger = false;

    // constructor logic

    public void beforeInsert()
    {
        if (bypassTrigger) return;

        // implementation logic
    }

    // other events
}

Then, in some test where you don’t actually care about the trigger, but need your records to exist in the database:

static testMethod void testSomeFunctionality()
{
    MyTriggerHandler.bypassTrigger = true;
    insert myRecords;
    MyTriggerHandler.bypassTrigger = false;

    // other stuff
}

Attribution
Source : Link , Question Author : Dan Jones , Answer Author : Adrian Larson

Leave a Comment