How to access private method? C #, VS 2012. Thank you. PS Former theme name - "Unit Test for private methods"

  • one
    1. If the class is yours and you need access to the method outside, why do you declare it private? 2. If the class is not yours, access to the private method does not make sense, since it (a) is not designed for this, (b) with the next update may disappear --- You can use reflection as a temporary hack, just don't include this is in production code. - VladD
  • Possible duplicate question: How to test private and protected methods? - Andrey NOP

3 answers 3

@Track (I’d definitely not fit in the comments :)

  • How can we talk about Unit tests, but do not go about refactoring?
  • When a product is developed, the developer has only two possible options - either to write normal production code, or to write-only code that immediately goes to the garbage ( Spike in the terminology of Extreme Programming ).

  • In the first case, Unit tests specify the behavior of this code and are inextricably linked with refactoring, since they allow reducing the number of errors during its execution.

  • In the second case, Unit tests are not needed by definition.

  • If we talk about the topic of the question, then testing private methods is meaningless for several reasons :
  • The hypothetical green Unit test for the private method does not give any knowledge about the behavior of the corresponding class. This private method may not be called at all from the public methods of the class, and you will add an unnecessary test, which must also be supported.

  • Contracts of private methods are extremely volatile. Today, let's say, the method is called SafelyCreateBlackBox(...) , and tomorrow - ReconstructContainerFromScratch(...) .

  • It completely contradicts the concept of TDD, in which the product design is dictated by the specification of its behavior in the form of a test suite. You will not begin development with a writing of tests for private methods of nonexistent classes? :)

  • The fact that at some point in time you wanted to write a test for a private method most likely means one of two things:
  • You have no tests and there is some class with a lot of responsibility. You are trying to verify the correctness of its behavior "piece by piece", for example, by starting with testing private methods. Correctly in this case, you need to understand what behavior is expected from the class, speculate this behavior in tests that use the public interface of the class and refactor this class in order to reduce the number of its responsibilities.

  • You have tests and it still seems to you that testing a private method is a good idea. In this case, most likely, the logic of the private method fits in well with some separate entity and can be removed from the original class. In this case, you need to come up with a name for the new entity, specify its behavior in the tests and remove it from the original class.

  • All right but off topic. If you had bothered to read my comment (to which you are answering) completely, you would understand what exactly is easier in this case to drop the testing in the Test Unit. To further confusion - renamed the topic. - Track
  • one
    @ Kitty: I’m happy to steal the last item for future discussions. :) - VladD 4:39 pm

To begin with, the private methods are not intended for testing. They are not part of the official "facade" of the class, they have the right to rely on invariants and preconditions to be met, but not to check them explicitly, they have the right to behave "incorrectly" when they are called within the framework of the workflow established for them.

You can, however, test internal methods. They will be available to the test assembly if you specify the InternalsVisibleTo attribute.

  • Of course, it is stupid to cover all private fields with tests, but sometimes it can be useful. - Track
  • one
    @Track: fields? - VladD pm
  • methods of course :) - Track

The solution is to use Reflection like this:

 var field = typeof(CopyItems).GetMethod(("FixRenamedPath"), BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static); string targetFile = (string)field.Invoke(null, new object[] { renamedFile, relatedFile, targetDir }); 
  • 3
    Perfect solution. Try now, with a set of tests written in this way, to do some Fowler refactoring such as the Rename Method or the Introduce Parameter Object. - Costantino Rupert
  • one
    @ Kitty: You would have the irony of reds. - VladD
  • It's not about refactoring. Without this test, referring to the public fields, it was necessary to prepare files (delete, copy, etc.) Of course, you could copy the method somewhere else or temporarily make it public. And why all this? Just because when private methods are not taken to test? :) But it is much easier to comment out two lines. - Track
  • @Track: private methods are like underwear: they are not shown to anyone. At any moment they have the right to be removed or altered, treacherously and without a declaration of war. Including them in a unit-test means that you are trying to fix their semantics, not to mention simply the presence and list of arguments. - VladD 5:48 pm
  • Well, yes - I absolutely agree. But from tests it is convenient to test. Oddly enough. When the private method is tested, you can comment out the lines in the test and forget about this method. But testing is just so convenient. - Track