dimanche 15 janvier 2017

Most reliable approach to mocking private members (as of 2017)

I understand we shouldn't test private methods/variables since that's an implementation detail, but I'm confused about the most reliable approach for mocking private variables/fields.

I had been relying on org.mockito.internal.util.reflection.Whitebox but this no longer works with Mockito 2.6.2. The answer here suggests implementing the setInternalState functionality of Whitebox - but I've noticed that org.powermock.reflect.Whitebox still works and isn't within an internal package. I don't want to rely heavily on it in my test suite only to have it break in a later PowerMock version. Is this reflection susceptible to breaking? Does it break encapsulation?

This answer instead says to inject the mock by adding a setter. But if the class I'm testing has 20+ private fields and I have to mock each of them in one test or another, this means I need to create setters for each? Wouldn't this essentially break encapsulation of my class (SUT)? Not to mention clutter up my class with ugly setters.

There also seems to be @RunWith(MockitoJUnitRunner.class) to inject mocks as shown here but that post is 4 years old and I wasn't getting the same instant solution as with WhiteBox. I'd prefer not to have to use a DI framework if I don't have to. What is the most reliable way to mock private variables/fields?

Example:

public class ClassA() {

 private PerformStats performStats;
 private DataModel dataModel;
 private String address;
 private int age;

 public ClassA() {
  //... initializers
 }

 public void someMethod() {
  age = dataModel.getAge(); // I want to used a mock dataModel here
 }

}

I could use Whitebox.setInternalState(ClassA, "dataModel", dataModel); in my test but I don't know if this is reliable long-term, or even recommended. Adding a setter for each field seems superfluous, and I'm unclear of its effect on encapsulation. What is the most reliable approach?





Aucun commentaire:

Enregistrer un commentaire