13

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?

3 Answers 3

14

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
}
1
  • 2
    It did occur to me after the question my particular use case would be better handled using JavaScript to be honest! I think I need some coffee. Regardless, I'll take into account what you say with respect to many developers who feel the @TestVisible annotation should never be used and avoid it like I avoid seealldata=true I think!
    – Dan Jones
    Oct 12, 2016 at 15:02
9

As an addendum to Adrian's answer:

I use a lot of custom messaging assigned to final strings and they have an access of private

@TestVisible private static final string REQERROR = 'There was an error processing your request';

Adding the @TestVisible annotation allows me to use this property in my test classes to assert the appropriate messages are displayed while allowing me to change the message and not break the test classes.

The alternative would be to make the access public but i like to only make things public when they need to be public.

You can find use cases for this in many places.

The one thing I would says is if you have a method that is private you should generally not need to use @TestVisible because the method itself is private and thus if a test does not cover it without the @TestVisible then either there is something wrong with your code, test, or the method is unused.

The exception to the above is a helper method that you make private. If you want to use the results of that method in your assertions then you would need to use the @TestVisible

5
  • if you have a method that is private you should generally not need to use @TestVisible because the method itself is private I like this quote. I guess otherwise it'd make more sense to make it public anyways. I did think @TestVisible was one of those methods that you ignore unless absolutely necessary and this isn't one of those scenarios. Thanks!
    – Dan Jones
    Oct 12, 2016 at 15:08
  • But a static final String is immutable. I make all my constants public since they cannot be changed by other classes. Why use private at all?
    – Adrian Larson
    Oct 12, 2016 at 15:16
  • 4
    @AdrianLarson - Because I only want the VF controller to use those messages and that is the only class where those messages will be used. Making them public indicates that they can be used anywhere. More of a reminder that the messages should only be used in that class. If that is not the case then public would be appropriate. Certainly no harm in making them public but private is more concrete.
    – Eric
    Oct 12, 2016 at 15:19
  • 1
    Fair enough. For me the no harm aspect makes it an obvious choice. I just find the use of the annotation more distasteful, but I see your point. Another option is to use Custom Label but that also has the issue of being used elsewhere.
    – Adrian Larson
    Oct 12, 2016 at 15:20
  • 2
    @AdrianLarson The declaration @TestVisible private communicates the intent exactly: the string is only referenced in the class and in tests. Using public gives the impression that the string is used in other classes too.
    – Keith C
    Oct 12, 2016 at 17:36
8

Generally, you'd use @TestVisible when you need to control the internal state of an object, or you need to observe the internal state of an object that can't be deduced from the outside. Generally speaking, this is only for particularly esoteric designs. I've personally never had a use for this annotation, but it can make writing some kinds of tests easier to perform.

In this case, I'd argue that since userList is observable from the outside, calling the method and observing the checked state of the users in the list would more desirable than making sure the internal state variable was correct; the state variable isn't directly tied to the users' selected state, and so testing it independently has no real value.

As an aside, your method is unnecessarily verbose. You could have written the code like this:

public void toggleAllUsers() {
  isAllUserSelected = !isAllUserSelected;
  for(uUser user: userList) {
    user.selected = isAllUserSelected;
  }
}
1
  • Perfect, thanks for this. It does make more sense to assert values of userList than it does to check this toggle.
    – Dan Jones
    Oct 12, 2016 at 15:06

You must log in to answer this question.

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