336

Visual Studio allows unit testing of private methods via an automatically generated accessor class. I have written a test of a private method that compiles successfully, but it fails at runtime. A fairly minimal version of the code and the test is:

//in project MyProj
class TypeA
{
    private List<TypeB> myList = new List<TypeB>();

    private class TypeB
    {
        public TypeB()
        {
        }
    }

    public TypeA()
    {
    }

    private void MyFunc()
    {
        //processing of myList that changes state of instance
    }
}    

//in project TestMyProj           
public void MyFuncTest()
{
    TypeA_Accessor target = new TypeA_Accessor();
    //following line is the one that throws exception
    target.myList.Add(new TypeA_Accessor.TypeB());
    target.MyFunc();

    //check changed state of target
}

The runtime error is:

Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.

According to intellisense - and hence I guess the compiler - target is of type TypeA_Accessor. But at runtime it is of type TypeA, and hence the list add fails.

Is there any way I can stop this error? Or, perhaps more likely, what other advice do other people have (I predict maybe "don't test private methods" and "don't have unit tests manipulate the state of objects").

Sibeesh Venu
  • 12,177
  • 5
  • 67
  • 98
junichiro
  • 4,402
  • 3
  • 15
  • 25
  • You need an accessor for private class TypeB. Accessor TypeA_Accessor provides access to private and protected methods of TypeA. However TypeB is not a method. It is a class. – Dima Apr 08 '13 at 22:13
  • Accessor provides access to private/protected methods, members, properties, and events. It does not provide access to private/protected classes within your class. And private/protected classes (TypeB) are intended to be used only by methods of owning class (TypeA). So basically you are trying to add private class (TypeB) from outside of TypeA to "myList" which is private. Since you are using accessor, there is no problem to access myList. However you can not use TypeB through accessor. Posiible solution would be to move TypeB outside of TypeA. But it can break your design. – Dima Apr 08 '13 at 22:23
  • Feel that testing private methods should be done by the following https://stackoverflow.com/questions/250692/how-do-you-unit-test-private-methods – nate_weldon Aug 30 '17 at 17:26

11 Answers11

748

You can use the PrivateObject class:

Class target = new Class();
PrivateObject obj = new PrivateObject(target);
var retVal = obj.Invoke("PrivateMethod");
Assert.AreEqual(expectedVal, retVal);

Note: PrivateObject and PrivateType are not available for projects targeting netcoreapp2.0 - GitHub Issue 366

phoenix
  • 3,988
  • 1
  • 29
  • 33
Scuttle
  • 7,569
  • 2
  • 11
  • 9
  • 29
    This is the correct answer, now that Microsoft has added PrivateObject. – Zoey Jan 27 '14 at 11:57
  • 4
    Good answer but please note that the PrivateMethod needs to be "protected" in stead of "private". – HerbalMart Mar 13 '14 at 11:54
  • How about invoking a method in an abstract class? (a class that can not be constructed on its own...). Instantiate a derived class? Hmmm not so nice. Some other reflection tricks? Anyone... ? – Mike de Klerk Apr 18 '14 at 19:20
  • 24
    @HerbalMart: Perhaps I misunderstand you, but if you are suggesting that PrivateObject can only access protected members and not private ones, you are mistaken. – kmote Jun 18 '14 at 18:37
  • @MikedeKlerk I think PrivateType class will help. For more details see http://stackoverflow.com/questions/4883944/privateobject-does-not-find-property – ClearCloud8 Jul 10 '14 at 15:07
  • and what about when the private method is void? – Rafal_Koscinski Jul 22 '14 at 09:02
  • 1
    @Rafal_Koscinski then what do you expect it to do? If it's void, it can run successfully or throw an exception. You can assert for exceptions when calling obj.Invoke("PrivateMethod") – Rast Dec 11 '14 at 16:58
  • @HerbalMart - it seems PrivateObject can be used with private methods now (not just protected). I just used it with a private method and it worked fine. Its a very useful feature! – namford Aug 05 '15 at 09:15
  • 1
    Would the suggestion work for a static class? If so, can you provide an example? – Jeff Pearce Feb 25 '16 at 21:12
  • 1
    How to resolve the problem with the refactoring of method name? – Dawid Wekwejt Mar 15 '17 at 08:05
  • 19
    @JeffPearce For static methods you can use "PrivateType pt = new PrivateType(typeof(MyClass));", and then call InvokeStatic on the pt object as you would call Invoke on a private object. – Steve Hibbert May 02 '17 at 09:45
  • Very useful this. Had this up and running in 5 minutes and gives me the confidence that stuff I feel rightly should be private, can also be unit tested. – Mike Upjohn Nov 02 '17 at 13:41
  • 13
    In case anyone was wondering as of MSTest.TestFramework v1.2.1 - the PrivateObject and PrivateType classes are unavailable for projects targeting .NET Core 2.0 - There's a github issue for this: https://github.com/Microsoft/testfx/issues/366 – shiitake Apr 12 '18 at 20:06
  • PrivateObject for `call method with parameters` ? – Kiquenet Jun 13 '18 at 13:32
  • 1
    PrivateObject for call ***static*** `method with parameters` ? – Kiquenet Jun 13 '18 at 13:32
  • 3
    @Kiquenet obj.Invoke("TestMethod", toPassIn); The method takes an array of objects as params – Lord Darth Vader Jun 27 '18 at 07:04
  • how to handle if "PrivateMethod" throws an exception? – anhtv13 Jul 05 '18 at 08:07
  • obj.Invoke("PrivateMethod") allows for a second parameter, an object array which represents your method parameters, e.g. obj.Invoke("PrivateMethod", myparams) where myparams is object[] – robnick Jan 10 '19 at 23:47
  • 1
    missing in ".NET Core 3+" as well, had to copy the source code files from Microsoft GitHub directly into my project – Aaron. S Jan 04 '20 at 23:09
  • 1
    to make the "code-smell" go away and to make the life of the testers easier, you can write `nameof(MyMethod)` instead of "MyMethod" – Bizhan Feb 05 '20 at 20:39
  • 1
    @Bizhan if `MyMethod` is private or protected, and it's inside another class, you won't be able to do this. – c-chavez Mar 11 '20 at 13:29
  • @c-chavez of course the code doesn't run on its own. You need to have an extra public constant. Generally it's a bad idea to write down the method/class names within double quotations. – Bizhan Mar 11 '20 at 15:03
  • 1
    @Bizhan I think this is also useful, but in some cases it could create a lot of new constants. I also agree there should be some sort of getting this property without a string, since if this name is changed, you won't see an error until you compile and run the tests. – c-chavez Mar 11 '20 at 15:16
  • @c-chavez that's a good argument, I didn't think of it in this context. *if the name changes the test simply fails.* – Bizhan Mar 11 '20 at 15:22
  • 1
    For `Assert.ThrowsException()` to work, you must catch `TargetInvocationException` from `Invoke()` or `InvokeStatic()`, and re-throw `InnerException`. – Christian Davén Jun 03 '20 at 06:37
283

Yes, don't unit test private methods.... The idea of a unit test is to test the unit by its public 'API'.

If you are finding you need to test a lot of private behavior, most likely you have a new 'class' hiding within the class you are trying to test, extract it and test it by its public interface.

One piece of advice / Thinking tool..... There is an idea that no method should ever be private. Meaning all methods should live on a public interface of an object.... if you feel you need to make it private, it most likely lives on another object.

This piece of advice doesn't quite work out in practice, but its mostly good advice, and often it will push people to decompose their objects into smaller objects.

Paul Childs
  • 249
  • 2
  • 8
Keith Nicholas
  • 41,161
  • 15
  • 82
  • 145
  • 471
    I disagree. In OOD, private methods and properties are an intrinsic way to not repeat yourself (https://en.wikipedia.org/wiki/Don%27t_repeat_yourself). The idea behind black box programming and encapsulation is to hide technical details from the subscriber. So it is indeed necessary to have non-trivial private methods and properties in your code. And if it's non-trivial, it needs to be tested. – AxD Aug 25 '16 at 23:48
  • 10
    its not intrinsic, some OO languages don't have private methods, private properties can contain objects with public interfaces which can be tested. – Keith Nicholas Aug 26 '16 at 00:28
  • 10
    The point of this advice, is if you your object do one thing, and are DRY, then there's often little reason to have private methods. Often private methods do something the object isn't really responsible for but is quite useful, if non trivial, then it generally is another object as its likely violating SRP – Keith Nicholas Aug 26 '16 at 00:31
  • 40
    Wrong. You may want to use private methods to avoid code duplication. Or for validation. Or for many other purposes which the Public world should not know about. – Jorj Mar 08 '17 at 06:46
  • 5
    no..... what you will find, is those methods need to live somewhere else otherwise you tend to violate SRP – Keith Nicholas Mar 08 '17 at 10:15
  • 4
    "Don't test private methods" - this is quite a statement, I'm really not sure I can agree. Do you documentation from Microsoft to back this up? – Neil Billingham Apr 18 '17 at 10:16
  • 5
    Microsoft isn't the source of truth, I have no idea if they have anything on the subject at all :) heck these ideas existed before Microsoft was even on board with the idea of unit testing! But the concept of how to deal with private methods was hugely discussed in the early extreme programming user groups by the people who promoted unit testing to the world. The idea being with aggressive refactoring, and SRP, there shouldn't be much need for private, and if there is, it should be easily tested through the public interface. – Keith Nicholas Apr 18 '17 at 12:03
  • 54
    When you've been dumped on an OO codebase so horrifically designed and asked to "incrementally improve it", it was a disappointment to find I couldn't had some first tests for private methods. Yeh, perhaps in the textbooks these methods wouldn't be here, but in the real world we have users who have product requirements. I can't just do a massive "Look at ma clean code" refactoring without getting some tests in the project to build off. Feels like another instance of forcing practising programmers into avenues that naively seem good, but fail to take account of real messy shit. – dune.rocks Apr 24 '17 at 09:51
  • 3
    This is a design process driven by something like TDD, when you are dealing with an existing code base and if it's terrible, then you use different techniques, though I'd still not test private methods, there's a good book "working effectively with legacy code" ( of which I was a contributor ) that deals with these issues exactly @dune.rocks – Keith Nicholas Apr 25 '17 at 08:52
  • 5
    @KeithNicholas If i try to write clean code, that means I'll extract parts of a large method out into smaller methods and call them from the originally large method. It makes sense to keep these new smaller methods in the same class and private, doesn't it? And frequently these smaller methods can contain some non-trivial logic that should be tested, and they might be reused many times. Do you mean to say that this logic should only be tested via the public originally large method? – Joe Dyndale Jul 11 '17 at 09:14
  • 2
    @JoeDyndale big methods decompose to smaller methods, good FIRST step. Next step is to break apart your objects into smaller SRP based ones. Your object is only ever going to get used through its public interface ( the unit under test) so test it through that. Non trivial hidden logic that cant be tested easily through the public interface usually is another object. I started with extreme programming and unit testing in 1999, never had to test a private method ever. I've seen people do it, and I always can always refactor their code into simpler OO code with composed objects. – Keith Nicholas Jul 11 '17 at 21:48
  • @KeithNicholas Sure, I agree with that, in the case of pure OOP. However, in a web service for example, one isn't necessarily doing pure OOP even though the language is C#. In my current project I have a service that accepts requests, and the code that handles them is basically procedural, using mostly DTOs and, of course, a lot of framework objects, but that's just because objects are the main language construct. One class accepts requests, and most of the code for handling them is in a handler class. Doesn't really make sense to divide the handler into many objects with public interfaces IMO – Joe Dyndale Jul 13 '17 at 08:44
  • @JoeDyndale Dunno what your code looks like. I do a lot of web api stuff, never had much need for private methods ( or at least none that can't be easily tested through the public interfaces . Can setup a chat sometime and look at some code if you like – Keith Nicholas Jul 13 '17 at 09:40
  • 2
    @KeithNicholas Maybe I'm just thinking about testing in a different (quite possibly worse) way. My methods can also be tested through the public interface, but then the program would have to either do a _lot_ of unnecessary work for each test, or test way too many things in one test. I could separate my extracted methods into separate classes with public interfaces, but not in a way that would make more sense than simply making the methods in the existing class public to begin with. The latter would be practical, but not strictly speaking correct IMO. – Joe Dyndale Jul 13 '17 at 10:06
  • 2
    "Yes, don't Test private methods.... The idea of a unit test is to test the unit by its public 'API'." - this is just simply wrong. If your unit (let's talk about a simple class) has its own internal requirements and it is met with some methods, I should be able to test them separately to see if the requirements are met. Just an example: the class externally seem to be working well, but internally it doesn't do some FIFO stuff, which increases the performance. Ok, the code works, but I want it to work THAT way, which was originally expected. – newhouse Dec 04 '17 at 07:19
  • 1
    @newhouse I'd have to see some code, my bet is you have too much functionality in one class and can be split..... a fifo is a separate entity. I started with extreme programming and unit testing in 1999, and 18 years later I haven't seen any code I think needs tests on private things, other than poorly factored code which often works ways better when teased apart – Keith Nicholas Dec 04 '17 at 10:37
  • @KeithNicholas I won't wrap out helper methods in any way out of a class, if it is depending on members of the user class and really an internal logic. Thus it should be private and not to be called by others. But I'd still want to unit test it, because lots of methods might depend on it. Yes, I could simply and I WILL unit-test the user methods, but it might speed up debugging if I see that the error is not the user-code, but the generic internal itself. Maybe this is marginal sometimes, but still exists. – newhouse Jan 26 '18 at 12:31
  • Wow... The endless debate / critique between DRY/KISS and SOLID. The one that you should use depends on the team you are working on and the type of software you are developing. Horizontal - fast one-time tools or Vertical - high dependency libraries. Neither works best in every case. And different languages are designed for these very two different cases. Good programmers know which to use where. tl;dr – TamusJRoyce Jan 31 '18 at 15:57
  • 1
    Let's assume, that I decompose the code and extract private methods to a class that can be tested from the assembly/dll. Now the question: how to hide this extracted class if I do not feel it should be provided in the public interface? To me it contradicts the goal of providing an usable interface as now the client of the assembly can see implementation details. – Jaro Feb 12 '18 at 18:16
  • 5
    @Jaro use the keyword internal on the class. It's exactly what it is meant for – Keith Nicholas Feb 12 '18 at 21:24
  • 4
    Although the advice of decomposing large classes into smaller classes and making private methods public sounds right, it isn't. You will end up with a lot of tiny classes, it will be a nightmare to read the code and understand it. – Mert Akcakaya Jun 19 '18 at 13:57
  • @MertAkcakaya not something I experience ( been programming for ~40 years now). Usually when people say that I find that they have the wrong abstractions. – Keith Nicholas Jun 19 '18 at 22:46
  • I'm not entirely sold on this and here is why. Say I have a method that is fairly large. ~300 lines are inside an if and another ~300 are in the else. What I'd prefer is something more like `x ? PrivateMethod1() : PrivateMethod2();` I'm not sure bringing these methods into a new class is the right solution, but I'd still like to test them separately from the public method. Furthermore making a new object creates now public interfaces to something that could have existed in only one place since it only pertains to this class. – vipero07 Aug 15 '18 at 18:14
  • 2
    @vipero07 if you have a if statement with 300 lines and another 300 lines in an else, then we aren't even on the same page about what good design is. To me this should never arise with well factored code. Which means there are likely multiple classes within your 600 odd lines of code. – Keith Nicholas Aug 15 '18 at 21:31
  • @KeithNicholas I don't necessarily disagree, however lets assume you haven't written the entire code base and want unit tests on the bits of code where you are fixing bugs. Slowly migrating towards a well factored code base over time... it just really isn't a solution to rewrite everything especially without a complete understanding of the intent of the code being fixed. Doubly so when considering the poor factorization to begin with. – vipero07 Aug 15 '18 at 22:31
  • 2
    @vipero07 sure, if your argument is that you are starting with bad code with bad design then sure you may need to do compromised things as intermediate steps. However, having said that I'd suggest potentially using https://refactoring.com/catalog/replaceMethodWithMethodObject.html . My original advice stands though, with well factored code you shouldn't need to test private methods, and for the most, you shouldn't need any private methods. If you feel you do need one, then it's worth thinking about why and is there a better design. – Keith Nicholas Aug 15 '18 at 22:54
  • @Ashtonian The thing I think people struggle with is they imagine their current design and can see all these problems with testing private parts and it seems "wrong". Thing is when you use it as a driving force to your design you end up with different designs. It's not about making things public and moving them to new classes, it's about making easily composable units. On the surface from what you say, on one hand you say you have something for storing files in the cloud and on the other hand you have a business driven convention for names, they sound like different conceptual things to me. – Keith Nicholas Jan 29 '19 at 02:22
  • Very solid advise, which i strive to follow. Do one thing and do it well. – ste2425 Oct 09 '19 at 10:17
  • The advice to only unit test public methods is not answering the question asked and is inappropriate when following TDD, where all code private or not requires unit tests. – sfkleach Feb 26 '20 at 09:22
  • 1
    @sfkleach no, TDD doesn't require private methods to be tested directly, in fact, it is actively discouraged. As soon as you test a private method you are coupling your tests to private functionality which is a bad thing, Tests should be easy to change and robust to internal implementation changes of "Units" – Keith Nicholas Feb 26 '20 at 20:35
  • @KeithNicholas happy to take this offline. However, I have found this to be dependent on the application domain. Many classes that I write have one public method but dozens of private methods. Trying to test the private methods via the public method is a self-inflicted challenge created by taking an inflexible approach. Here's a thought experiment. If it was trivial to write unit tests for private methods, would anyone honestly be holding this line? Or would they simply divide their unit tests into those that test public behaviour and those that test implementation? – sfkleach Feb 28 '20 at 09:43
  • @sfkleach right, when that is a challenge, then like I say, you likely have a hidden object inside another that you are trying to keep private... It's not a thought experiment, Kent beck who popularized unit testing did it in smalltalk with no privates, just well factored objects. – Keith Nicholas Feb 29 '20 at 10:08
  • 1
    this is why software engineering is dead. everyone and his granny taking to the computers and pontificating on the internet. – Boppity Bop Mar 09 '20 at 18:11
  • 1
    "Don't do it" just doesn't work. As said above, private methods used to remove code duplication, or created during refactoring from longer method. I would say, methods should be marked 'private' if possible for better encapsulation. Unit testing is different subject. To tell "make private methods public" is like "we don't carry bath tissue, but we have sandpaper". – Andrei Kalantarian Jul 13 '20 at 20:43
  • @AndreiKalantarian I think you missed the point, it's not "make private methods public" your public interface should be coherent. Instead, when you feel you need to test the private methods it tends to be an indicator you actually have another object hidden behind the public interface. The point is about increasing modularity and making your software more composable. If you extract a smaller functional module, you can test it as a unit. – Keith Nicholas Jul 13 '20 at 21:44
  • @KeithNicholas encapsulation has its uses... not all APIs should expose all the underlying functionality. I'd almost argue the inverse of what you're saying. https://softwareengineering.stackexchange.com/a/143739/88135 – defines Sep 18 '20 at 20:24
  • @defines I think you missed the idea. You DON'T simply make private methods public. the methods on your public objects should make sense. The point is, your private methods are generally public methods on OTHER objects. It is still all encapsulated. Keep in mind Alan Kay ( inventor of OO ) smalltalk only has public interfaces. If you struggle to find how to separate out your private stuff from public stuff, then likely you have a design problem – Keith Nicholas Sep 20 '20 at 23:27
  • No, I did not miss that idea. I disagree with it. SRP doesn't preclude private members or encapsulation. – defines Sep 21 '20 at 13:58
  • @defines doesn't include the concept of private either. Encapsulation doesn't need the idea of private either. My experience is that people who tend to object to this idea tend to write very rigid objects, but the more you write modular composable objects the more obvious this idea is. This idea was born in the early days of the TDD world where people were striving for simple well factored designs, but much of the spirit of achieving simple design got lost as more people adopted TDD / unit testing and we now have rigid systems tested into further rigidity by unit tests – Keith Nicholas Sep 21 '20 at 22:15
  • How do you maintain both SRP and encapsulation without private? I'd love an example. – defines Sep 22 '20 at 17:43
  • @defines ah, point of clarification, in OO, the only public thing is the messages you can send an object ( or methods you can call on an object). All fields are private / no way to access them ( however some quasi OO languages allow you access to them) so, any objects that an object sends messages to are encapsulated to that object, it's transparent to its public interface. The point here is "private" is like messaging yourself, so instead, delegate to something else to handle that message, then you can test the "something else" via its public interface, ie factor into more composable modules – Keith Nicholas Sep 22 '20 at 21:39
  • That does make more sense. I think we were operationalizing the word "private" in different ways. – defines Nov 09 '20 at 18:15
  • Testing public interfaces make sense, but so do testing the business logic within those interfaces. What's different is the consumers. Developers should be the consumers of unit test results, QA and other stake holders should care about the interfaces. Saying a developer shouldn't unit test the "private" code is bad practice. If there's business logic, it should be considered testable, and at as a low a level as possible. What has been described in most of this thread is not "unit testing" from a dev perspective. – barna10 Mar 03 '21 at 17:21
  • @barna10 think you missed the point entirely and confusing the different kinds of testing, integration, and functional. the point is business logic should be public on a class, if it is hidden as private logic, its likely your class design is not very good and doing too much – Keith Nicholas Mar 04 '21 at 00:46
  • Sorry, not missing the point at all. If there's logic, it should be tested. Where it resides does not matter. Basing decisions on what should or shouldn't be tested is a separate discussion from system design decisions. There are plenty of reasons to make logic private that go beyond "your class design is not very good and doing too much". Style rules do not reign supreme. – barna10 Mar 05 '21 at 12:08
  • like I've said to others, give me an example of a piece of logic that should be private and not a public method on a different class that actually needs unit testing directly – Keith Nicholas Mar 07 '21 at 01:44
  • https://github.com/dotnet/runtime/blob/main/src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs Line 194. If that doesn't need unit tested, then we have a different concept of the term "unit". – barna10 Mar 14 '21 at 03:07
  • 1
    I have an optimization problem using Levenburg Marquardt around an ODE. All the Solvers are abstracted out and reusable. But the implementation of this problem is tightly coupled and the "bottom-half" ODE problem exposes strange metrics the "top-half" of the optimizer consumes. I'd like to test the IVP shooting method in isolation. To do so I need to make it public and extracting to a separate class is a distraction. Nothing else in the world should ever call it other than the optimizer or the tests. The problem is inherently tightly coupled and complicated. – lamont Mar 28 '21 at 18:16
  • 1
    I am also unaware of any similar problem that uses a similar solution anywhere in the trajectory optimization literature, it is a true one-off. AFAIK nobody in the universe wants reuseability of anything in this algorithm. I can move it to a public class with a public method fairly trivially, but that is a distraction from the fact that making it public is only for the purposes of testing and I can get the same effect from slapping "public" on the method. – lamont Mar 28 '21 at 18:21
109

“There is nothing called as standard or best practice, probably they are just popular opinions”.

Same holds true for this discussion as well.

enter image description here

It all depends on what you think is a unit , if you think UNIT is a class then you will only hit the public method. If you think UNIT is lines of code hitting private methods will not make you feel guilty.

If you want to invoke private methods you can use "PrivateObject" class and call the invoke method. You can watch this indepth youtube video ( http://www.youtube.com/watch?v=Vq6Gcs9LrPQ ) which shows how to use "PrivateObject" and also discusses if testing of private methods are logical or not.

Community
  • 1
  • 1
Shivprasad Koirala
  • 23,328
  • 7
  • 76
  • 65
  • 2
    All the pedantic wankery in our field causes more problems than it solves. This is why one of my programming teachers said, "Make everything public!" – codewise Dec 10 '20 at 20:58
71

Another thought here is to extend testing to "internal" classes/methods, giving more of a white-box sense of this testing. You can use InternalsVisibleToAttribute on the assembly to expose these to separate unit testing modules.

In combination with sealed class you can approach such encapsulation that test method are visible only from unittest assembly your methods. Consider that protected method in sealed class is de facto private.

[assembly: InternalsVisibleTo("MyCode.UnitTests")]
namespace MyCode.MyWatch
{
    #pragma warning disable CS0628 //invalid because of InternalsVisibleTo
    public sealed class MyWatch
    {
        Func<DateTime> _getNow = delegate () { return DateTime.Now; };


       //construktor for testing purposes where you "can change DateTime.Now"
       internal protected MyWatch(Func<DateTime> getNow)
       {
           _getNow = getNow;
       }

       public MyWatch()
       {            
       }
   }
}

And unit test:

namespace MyCode.UnitTests
{

[TestMethod]
public void TestminuteChanged()
{
    //watch for traviling in time
    DateTime baseTime = DateTime.Now;
    DateTime nowforTesting = baseTime;
    Func<DateTime> _getNowForTesting = delegate () { return nowforTesting; };

    MyWatch myWatch= new MyWatch(_getNowForTesting );
    nowforTesting = baseTime.AddMinute(1); //skip minute
    //TODO check myWatch
}

[TestMethod]
public void TestStabilityOnFebruary29()
{
    Func<DateTime> _getNowForTesting = delegate () { return new DateTime(2024, 2, 29); };
    MyWatch myWatch= new MyWatch(_getNowForTesting );
    //component does not crash in overlap year
}
}
Tomas Kubes
  • 20,134
  • 14
  • 92
  • 132
Jeff
  • 1,237
  • 10
  • 8
  • I'm not sure I understand. InternalsVisibleToAttribute makes methods and attributes which are marked as "internal" accessible, but my fields and methods are "private". Are you suggesting I change things from being private to internal? I think I misunderstand. – junichiro Feb 03 '12 at 02:36
  • 2
    Yes, that's what I'm suggesting. It's a little bit "hacky", but at least they're not "public". – Jeff Mar 15 '12 at 01:04
  • 32
    This is a wonderful answer **just** because it doesn't say "don't test private methods" but yes, it's quite "hacky". I wish there was a solution. IMO it's bad to say "private methods shouldn't be tested" because the way **I** see it: it's equivalent to "private methods shouldn't be correct". – MasterMastic Jun 06 '13 at 17:25
  • 5
    ya ken, I also confused by those who claim that private methods shouldn't be tested in unit test. Public API are the output, but sometimes wrong implementation also give the right output. Or the implementation made some bad side effects, e.g. holding resources that are not necessary, referencing objects preventing it from being collected by gc...etc. Unless they provide other test that can cover the private methods rather than unit test, otherwise I would consider that they can't maintain a 100% tested code. – mr.Pony Jun 10 '13 at 09:59
  • I agree with MasterMastic. This should be the accepted answer. – XDS Nov 06 '18 at 12:21
  • 2
    Nice. I was not aware of this. Exactly what I needed. Let's say I build a 3rd party component for others to use, but I only want to expose a very limited API. Internally it's quite complex and I would like to test individual components (like an input parser or validator for example), but i don't want to make those public. The end-user shouldn't need to know anything about those. I know the standard approach here is "test only your public API", but I would prefer testing single responsibility units of code instead. This allows me to do it without making them public. – kowgli Feb 25 '19 at 19:12
  • 1
    I think it should be the accepted answer too. Debate about private method testing is cool to read, but it's more a matter of opinion. As I see it pretty good arguments have been made on both sides. If you still want/need to test private methods, you should have a way to. This is the only one that was provided. Additionally, you can do it for a whole assembly, using : [assembly: InternalsVisibleTo("UT.cs")] in your AssemblyInfo.cs – mgueydan Sep 02 '19 at 12:07
  • 1
    I used this method but my assemblies were strongly named. So I had to make my unit test dll also strongly named and added this to my assembly. [assembly:InternalsVisibleTo("Name of your unit test assembly here,PublicKey=e05516a3****")] – Novice in.NET Sep 10 '19 at 15:22
  • Found this article talking about this concept too. I think it could be useful. https://improveandrepeat.com/2019/12/how-to-test-your-internal-classes-in-c/ – darkgaze Nov 27 '20 at 09:23
32

One way to test private methods is through reflection. This applies to NUnit and XUnit, too:

MyObject objUnderTest = new MyObject();
MethodInfo methodInfo = typeof(MyObject).GetMethod("SomePrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance);
object[] parameters = {"parameters here"};
methodInfo.Invoke(objUnderTest, parameters);
Jack Davidson
  • 3,242
  • 2
  • 26
  • 28
  • `call methods` ***static*** and ***non static*** ? – Kiquenet Jun 13 '18 at 13:35
  • 2
    The downside of reflection-reliant methods is that they tend to break when you rename methods using R#. It might not be a big problem on small projects but on huge code-bases it becomes kinda nagging to have unit tests breaking in such a fashion and then having to go around and quick-fix them. In this sense I my money goes to Jeff's answer. – XDS Nov 06 '18 at 12:23
  • 2
    @XDS Too bad nameof() doesn't work to get the name of a private method from outside its class. – Gabriel Morin Feb 06 '19 at 20:29
16

Ermh... Came along here with exactly the same problem: Test a simple, but pivotal private method. After reading this thread, it appears to be like "I want to drill this simple hole in this simple piece of metal, and I want to make sure the quality meets the specs", and then comes "Okay, this is not to easy. First of all, there is no proper tool to do so, but you could build a gravitational-wave observatory in your garden. Read my article at http://foobar.brigther-than-einstein.org/ First, of course, you have to attend some advanced quantum physics courses, then you need tons of ultra-cool nitrogenium, and then, of course, my book available at Amazon"...

In other words...

No, first things first.

Each and every method, may it private, internal, protected, public has to be testable. There has to be a way to implement such tests without such ado as was presented here.

Why? Exactly because of the architectural mentions done so far by some contributors. Perhaps a simple reiteration of software principles may clear up some missunderstandings.

In this case, the usual suspects are: OCP, SRP, and, as always, KIS.

But wait a minute. The idea of making everything publicly available is more of less political and a kind of an attitude. But. When it comes to code, even in then Open Source Community, this is no dogma. Instead, "hiding" something is good practice to make it easier to come familiar with a certain API. You would hide, for example, the very core calculations of your new-to-market digital thermometer building block--not to hide the maths behind the real measured curve to curious code readers, but to prevent your code from becoming dependent on some, perhaps suddenly important users who could not resist using your formerly private, internal, protected code to implement their own ideas.

What am I talking about?

private double TranslateMeasurementIntoLinear(double actualMeasurement);

It's easy to proclaim the Age of Aquarius or what is is been called nowadays, but if my piece of sensor gets from 1.0 to 2.0, the implementation of Translate... might change from a simple linear equation that is easily understandable and "re-usable" for everybody, to a pretty sophisticated calculation that uses analysis or whatever, and so I would break other's code. Why? Because they didn't understand the very priciples of software coding, not even KIS.

To make this fairy tale short: We need a simple way to test private methods--without ado.

First: Happy new year everyone!

Second: Rehearse your architect lessons.

Third: The "public" modifier is religion, not a solution.

CP70
  • 219
  • 2
  • 3
  • I agree completely. I'm also wondering what we should do, in case of selling a product that contains code. We have to be clear about the public API but it is great to have a bunch of tests for the internal functionality too. If everything is tested, and small, it will probably work correctly. But those little functions that nobody has to call, need to be tested too! – darkgaze Nov 27 '20 at 09:18
8

Another option that has not been mentioned is just creating the unit test class as a child of the object that you are testing. NUnit Example:

[TestFixture]
public class UnitTests : ObjectWithPrivateMethods
{
    [Test]
    public void TestSomeProtectedMethod()
    {
        Assert.IsTrue(this.SomeProtectedMethod() == true, "Failed test, result false");
    }
}

This would allow easy testing of private and protected (but not inherited private) methods, and it would allow you to keep all your tests separate from the real code so you aren't deploying test assemblies to production. Switching your private methods to protected methods would be acceptable in a lot of inherited objects, and it is a pretty simple change to make.

HOWEVER...

While this is an interesting approach to solving the problem of how to test hidden methods, I am unsure that I would advocate that this is the correct solution to the problem in all cases. It seems a little odd to be internally testing an object, and I suspect there might be some scenarios that this approach will blow up on you. (Immutable objects for example, might make some tests really hard).

While I mention this approach, I would suggest that this is more of a brainstormed suggestion than a legitimate solution. Take it with a grain of salt.

EDIT: I find it truly hilarious that people are voting this answer down, since I explicitly describe this as a bad idea. Does that mean that people are agreeing with me? I am so confused.....

Roger Hill
  • 2,444
  • 1
  • 29
  • 32
4

From the book Working Effectively with Legacy Code:

"If we need to test a private method, we should make it public. If making it public bothers us, in most cases, it means that our class is doing too much and we ought to fix it."

The way to fix it, according to the author, is by creating a new class and adding the method as public.

The author explains further:

"Good design is testable, and design that isn't testable is bad."

So, within these limits, your only real option is to make the method public, either in the current or a new class.

Kai Hartmann
  • 2,876
  • 25
  • 38
  • 2
    Secure coding practices dictate that we should make everything private unless it absolutely needs to be public, like an API interface. If every little thing in your program is somewhere defined as public then it could be called by malicious actors to use your code to attack the system. You want to reduce the attack surface of your binaries while also being testable. – HackSlash Aug 21 '20 at 21:37
  • 1
    @hackslash making things private doesn't hide anything and doesn't prohibit other assemblies or objects from actually calling them. It just adds compile time type checking. – CervEd Dec 15 '20 at 23:15
  • 2
    This is sound advice to consider when faced with this problem, but definitely not the go-to answer. Essentially it says "never use private methods" (or alternatively: don't test all your methods). In fairy tale academia or in-house app development scenarios that might work. But forget it for a complex library with a public API. Imagine you already have a complex library with a large object graph of inter-dependent classes. Now make it WAY more difficult by moving all private code to new dummy classes and somehow share state with them. – enzi Apr 20 '21 at 12:55
  • Instead of answering the original question ("how do I test private methods?"), this resposnse instead answers the question that no one has asked ("should I test private methods?"). – bazzilic May 11 '21 at 08:14
2

Extract private method to another class, test on that class; read more about SRP principle (Single Responsibility Principle)

It seem that you need extract to the private method to another class; in this should be public. Instead of trying to test on the private method, you should test public method of this another class.

We has the following scenario:

Class A
+ outputFile: Stream
- _someLogic(arg1, arg2) 

We need to test the logic of _someLogic; but it seem that Class A take more role than it need(violate the SRP principle); just refactor into two classes

Class A1
    + A1(logicHandler: A2) # take A2 for handle logic
    + outputFile: Stream
Class A2
    + someLogic(arg1, arg2) 

In this way someLogic could be test on A2; in A1 just create some fake A2 then inject to constructor to test that A2 is called to the function named someLogic.

darkgaze
  • 1,836
  • 4
  • 30
  • 54
o0omycomputero0o
  • 2,604
  • 2
  • 27
  • 40
0

In VS 2005/2008 you can use private accessor to test private member,but this way was disappear in later version of VS

Allen
  • 559
  • 10
  • 19
  • 1
    Good answer back in 2008 to perhaps early 2010. Now please refer to PrivateObject and Reflection alternatives (see several answers above). VS2010 had accessor bug(s), MS deprecated it in VS2012. Unless you are forced to stay in VS2010 or older (>18 years old build tooling) please save yourself time by avoiding private accessors. :-). – Zephan Schroeder Mar 01 '19 at 01:27
0

I use this helper (object type extension)

 public static  TReturn CallPrivateMethod<TReturn>(
        this object instance,
        string methodName,
        params object[] parameters)
    {
        Type type = instance.GetType();
        BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Instance;
        MethodInfo method = type.GetMethod(methodName, bindingAttr);

        return (TReturn)method.Invoke(instance, parameters);
    }

You can call it like this

Calculator systemUnderTest = new Calculator();
int result = systemUnderTest.CallPrivateMethod<int>("PrivateAdd",1,8);

One of the advantages is that it uses generics to pre-determine return type.

lstanczyk
  • 1,195
  • 12
  • 19