7

Is it possible to get access to a private field in a unit test?

Michelle
  • 601
  • 1
  • 8
  • 17

6 Answers6

11

The way to get private fields or methods in general is to use Reflection. However, the unit test framework includes a helper class, PrivateObject, to make this easier. See the docs. In general, when I've used this, I've ended up making an extension methods like the following:

public static int GetPrivateField(this MyObject obj)
{
  PrivateObject po = new PrivateObject(obj);
  return (int)po.GetField("_privateIntField");
}

If you need to get private fields in a static class, however, you will need to go with straight up reflection.

Mike Zboray
  • 39,828
  • 3
  • 90
  • 122
  • 2
    You can get and set private fields in a static class using a [`PrivateType`](http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.privatetype.aspx) object (as opposed to the PrivateObject type!) – stuartd Feb 21 '13 at 23:17
2

Nice solution offered above. For completeness, I have been using this technique for a while now (using MSTest), but have extended it for property values also.

[ExcludeFromCodeCoverage]
public static class TestExtensionMethods
{
    public static T GetFieldValue<T>(this object sut, string name)
    {
        var field = sut
            .GetType()
            .GetField(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

        return (T)field?.GetValue(sut);
    }

    public static T GetPropertyValue<T>(this object sut, string name)
    {
        var field = sut
            .GetType()
            .GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

        return (T)field?.GetValue(sut);
    }
}
Regianni
  • 229
  • 1
  • 3
  • 11
1

No. If you're writing good Unit Tests, you shouldn't need to access any private fields. Unit Tests should test that when passed in a known set of values, a method behaves a certain way (either by returning the appropriate data or using the dependencies in a known fashion).

If you're trying to test the later, use Dependency Injection to inject the dependencies into the class you're testing. You'll have full access to those dependencies for your tests.

Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • Thank you guys I didn't realize that I was violating the TDD principles. Thank you – Michelle May 28 '12 at 20:05
  • 5
    The question was whether it was possible, not whether it is a best practise. – stuartd Feb 21 '13 at 23:22
  • While I agree with Justin in theory, in practice one often has to write unit tests for sub-optimal code that cannot be changed or cannot be easily changed. – Dave Jan 27 '14 at 21:23
1

Not saying it's a good idea but I've seen InternalsVisibleTo used.

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

Look at this Q. One of the more unpopular answers:

Unit testing and checking private variable value

Community
  • 1
  • 1
tzerb
  • 1,433
  • 1
  • 16
  • 35
1

Testing is about catching defects, and TDD is about catching defects as early as possible. You need about as many test conditions as there is cyclomatic complexity in you code. Complexity beyond a certain amount is difficult to debug; that is why we break complicated tasks into less complicated functions. Some public tasks require a great deal of overall complexity, and that complexity is better managed by dividing it into smaller routines. Now, why would you want to suffer the combinatorial explosion of test conditions all at the higher level function when you could write simpler tests for the lower level functions?

It does not matter if your methods are public or private. The complexity of the method is the most important factor in how likely there is to be a defect in it. You will find and fix defects faster if you only have to test a little bit of complexity at a time.

Say you have broken complicated task A into less complicated tasks X, Y, and Z. If you test only at A, you could find yourself needing X * Y * Z test conditions instead of X + Y + Z conditions.

ChrisG65
  • 59
  • 2
0

I know this is old but would like to add my 2 cents worth on testing private methods.

I agree that in most cases testing the public-facing methods is good enough, but that isn't always the case.

I can think of two examples off the top of my head that being able to test private methods would be great and produce fewer tests.

Case 1: Reports: I have an application that produces reports based upon a large amount of data as in close to 100 data points. Many of these data points are dependent on one or more other data points. To make sure each code path is tested would require 1000s of the test.

Case 2: Logically complex methods: I am working on a project right now that 3 or 4 short but complex chunks of logic are buried deep in the class. It would be handy to be able to unit test these is a develop them. I am porting from another language and these methods have changed in over 15 years. So it isn't like they will be brittle.

I try to follow the 3 Laws of TDD which is really hard to do with a lot of private methods.

I am just saying that are times and reasons that unit testing private methods is desirable.

Darryl Wagoner WA1GON
  • 967
  • 1
  • 10
  • 31