So from the docs I understand that
@TestVisible
is used to allow Unit Tests access toprivate
andprotected
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 isprivate
?
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