507

I'm building a class library that will have some public & private methods. I want to be able to unit test the private methods (mostly while developing, but also it could be useful for future refactoring).

What is the correct way to do this?

Eric Labashosky
  • 29,484
  • 14
  • 39
  • 32
  • 3
    I may be missing something, or maybe it's just that this question is, well... `pre-historic` in term of Internet years, but unit testing of private methods is now both easy and straight forward, with Visual Studio producing the necessary accessor classes when needed and pre-filling the tests logic with snippets damn close to what one may desire for simple functional tests. See for eg. http://msdn.microsoft.com/en-us/library/ms184807%28VS.90%29.aspx – mjv Aug 10 '11 at 23:00
  • 5
    This seems a near duplicate of http://stackoverflow.com/questions/34571/whats-the-proper-way-to-test-a-class-with-private-methods-using-junit. – Raedwald Oct 06 '11 at 12:49
  • The questioner may not be using visual studio – Dave Dec 04 '14 at 10:16
  • 6
    Don't unit test internals: http://blog.ploeh.dk/2015/09/22/unit-testing-internals – Mark Seemann Sep 28 '15 at 07:45
  • 1
    Possible duplicate of [How do I test a class that has private methods, fields or inner classes?](https://stackoverflow.com/questions/34571/how-do-i-test-a-class-that-has-private-methods-fields-or-inner-classes) – Raedwald Dec 14 '17 at 12:30
  • The Private Accessors are deprecated in Visual Studio as of 2012. – Blaine DeLancey Jul 23 '18 at 16:33
  • The question isn't whether he SHOULD test a private method rather it is HOW can he test a private method. I am not arguing the merits of either way. There might be a legitimate reason that he wants to do this, along with everyone else that ends up here looking for a solution. – Nathan Oct 20 '20 at 15:08
  • Related post - [Unit testing private methods in C#](https://stackoverflow.com/q/9122708/465053) – RBT Jun 29 '21 at 04:25

32 Answers32

361

If you want to unit test a private method, something may be wrong. Unit tests are (generally speaking) meant to test the interface of a class, meaning its public (and protected) methods. You can of course "hack" a solution to this (even if just by making the methods public), but you may also want to consider:

  1. If the method you'd like to test is really worth testing, it may be worth to move it into its own class.
  2. Add more tests to the public methods that call the private method, testing the private method's functionality. (As the commentators indicated, you should only do this if these private methods's functionality is really a part in with the public interface. If they actually perform functions that are hidden from the user (i.e. the unit test), this is probably bad).
Jeroen Heijmans
  • 4,546
  • 2
  • 17
  • 16
  • 43
    Option 2 makes the unit tests have to have knowledge of the underlying implementation of the function. I don't like doing that. I generally think unit tests should test the function without assuming anything about implementation. – Herms Oct 30 '08 at 16:01
  • 17
    Disadvantages of testing implementation is that the tests will be fragile to break if you introduce any changes to the implementation. And this is undesirable as refactoring is as important as writing the tests in TDD. – JtR Oct 30 '08 at 16:04
  • 32
    Well, the tests *are supposed* to break if you change the implementation. TDD would mean changing the tests first. – sleske Apr 22 '09 at 17:11
  • 42
    @sleske - I don't quite agree. If the *functionality* hasn't changed, then there's no reason the test should break, since tests should really be testing behaviour/state, not implementation. This is what jtr was meaning about it making your tests fragile. In an ideal world, you should be able to refactor your code and have your tests still pass, verifying that your refactoring hasn't changed the functionality of your system. – Alconja May 28 '09 at 00:10
  • 4
    @sleske and @alconja/jtr - i think you both mean diff things by break - sleske - test failures. alconja/jtr mean compile failures. private methods undergo rapid refactoring.. tests that have knowledge of the private methods thereby tend to be fragile.. as in you need to go back and modify the test code with changes in implementation. The righteous path :) is that a test shouldn't have to change unless the requirement/functionality/behavior changes – Gishu Aug 29 '09 at 06:38
  • 34
    Apologies for naivety (not much experience with testing as yet), but isn't the idea of unit testing to test every code module on its own? I don't really understand why private methods should be excluded from this idea. – OMill Jun 09 '11 at 10:59
  • 14
    I also use Unit Tests as a sort of test harness - I can very quickly test little bits of my application without, for example, creating a GUI to test them. In this scenario, I find testing private methods very useful. – Ryan Shripat Sep 09 '11 at 15:56
  • 2
    @OMill The problem is in what a "code module" is. This is typically some class that implements an interface. If you start eviscerating the class and making calls in its guts willy nilly, you can't expect it to uphold its guarantees about consistent state. Also, if you're interested in testing the behavior of private methods, why stop there? Who will test the behavior of our individual LOC, or statements, or expressions? – Asad Saeeduddin Aug 11 '15 at 20:07
  • 6
    Consider this scenario: A class, containing business logic where all methods are private and only 1 method is public - UpdateData(myType myObject). Why expose the class internals? Outsiders should not know what's involved into the update. I really don't want to test the update itself, but data transformation and validation, etc, happening before the update. The class is very small and I can't justify creating separate classes with public methods each containing a single method for validation, transformation, etc. It's far simpler to unit-test private methods of the class. – sasharz Aug 13 '15 at 19:57
  • 2
    Good tests work bottom up, not top down. Private methods are often internal foundation requiring their own tests. And these tests often are best kept in another assembly...hence the problem. – Brendan Aug 02 '16 at 17:58
  • 1
    *"If the method you'd like to test is really worth testing, it may be worth to move it into its own class."* The problem with moving the method to it's own class, is that others might try to use the class, or call the methods. That class, and those methods, need to absolutely forbidden to be called or referenced from anyone other than the original method inside the class that used them. If you refactor them out to a separate class: you leave yourself open to bugs and crashes as you expose your internal implementation details. – Ian Boyd Nov 14 '21 at 16:30
127

If you are using .net, you should use the InternalsVisibleToAttribute.

Raedwald
  • 46,613
  • 43
  • 151
  • 237
TcKs
  • 25,849
  • 11
  • 66
  • 104
  • 89
    Yuck. This gets compiled into your released assemblies. – Jay Oct 28 '10 at 18:46
  • 16
    @Jay - couldn't one use `#if DEBUG` around the `InternalsVisibleTo` attribute to make it not apply to release code? – mpontillo Dec 01 '10 at 21:42
  • 21
    @Mike, you could, but then you can only run unit tests on debug code, not release code. Since Release code is optimized, you might see different behavior and different timings. In multithreaded code this means your unit tests won't appropriately detect race conditions. Much better is to use reflection via @AmazedSaint's suggestion below or use the built-in PrivateObject/PrivateType. This allows you to see privates in Release builds assuming your test harness is running with full trust (which MSTest running locally does) – Jay Dec 09 '10 at 03:16
  • 127
    What am I missing? Why would this be the accepted answer when it doesn't actually answer the specific question of testing private methods? InternalsVisibleTo only exposes methods marked as internal and not those marked private as requested by the OP (and the reason I landed here). I guess I need to continue using PrivateObject as answered by Seven? – Darren Lewis May 25 '11 at 13:34
  • I don't understand, how does that even solve the answer one single bit. – p0lAris Jun 30 '13 at 09:26
  • 6
    @Jay I know this is a bit late-coming, but one option is to use something like `#if RELEASE_TEST` around `InternalsVisibleTo` like Mike suggests, and make a copy of your release build configuration that defines `RELEASE_TEST`. You get to test your release code with optimizations, but when you actually build for release, your tests will be omitted. – Shaz Jul 24 '13 at 17:52
  • The linked article in the answer no longer exists – David Vogel Sep 24 '15 at 17:56
  • 6
    @Jay - Forgive me for my ignorance, but what's so bad about that attribute being compiled into your released assemblies? – BornToCode Jul 28 '16 at 16:54
  • 1
    I agree that this answer does not apply to the testing of private methods, only internal methods. From my cursory reading/Googling as I try to deal with a similar issue, it appears use of PrivateObject seems more relevant. – Blaine DeLancey Jul 23 '18 at 16:31
  • @Jay We **want** unit test code released into our production assemblies. That is how the self-tests (e.g. unit, functional, integration) can be done in the live production environment. – Ian Boyd Nov 14 '21 at 16:25
122

It might not be useful to test private methods. However, I also sometimes like to call private methods from test methods. Most of the time in order to prevent code duplication for test data generation...

Microsoft provides two mechanisms for this:

Accessors

  • Go to the class definition's source code
  • Right-click on the name of the class
  • Choose "Create Private Accessor"
  • Choose the project in which the accessor should be created => You will end up with a new class with the name foo_accessor. This class will be dynamically generated during compilation and provides all members public available.

However, the mechanism is sometimes a bit intractable when it comes to changes of the interface of the original class. So, most of the times I avoid using this.

PrivateObject class The other way is to use Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject

// Wrap an already existing instance
PrivateObject accessor = new PrivateObject( objectInstanceToBeWrapped );

// Retrieve a private field
MyReturnType accessiblePrivateField = (MyReturnType) accessor.GetField( "privateFieldName" );

// Call a private method
accessor.Invoke( "PrivateMethodName", new Object[] {/* ... */} );
Pang
  • 9,564
  • 146
  • 81
  • 122
Seven
  • 4,353
  • 2
  • 27
  • 30
  • 3
    How do you invoke private static methods? – StuperUser Jun 29 '12 at 10:22
  • 20
    Private accessors are [deprecated in Visual Studio 2012](http://msdn.microsoft.com/en-us/library/vstudio/hh507838.aspx). – Ryan Gates Nov 01 '12 at 23:00
  • 3
    The accessor method of testing Private Methods is being deprecated from VS 2011 onwards. http://blogs.msdn.com/b/visualstudioalm/archive/2012/03/08/what-s-new-in-visual-studio-11-beta-unit-testing.aspx – Sanjit Misra Mar 25 '13 at 09:17
  • 1
    Reading the docs found on Microsoft's website [here](http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.privateobject.aspx) I don't see any mention of the PrivateObject class being deprecated. I'm using MSVS 2013 and it works as expected. – stackunderflow Nov 26 '13 at 23:36
  • 3
    @RyanGates The first solution on the site you referenced states that the solution to access private members is to **"Use the PrivateObject class to assist in accessing internal and private APIs in your code. This is found in the Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll assembly."** – stackunderflow Nov 26 '13 at 23:40
  • The PrivateObject approach worked fine for me in VS2017. I didn't try the "Private Accessor" approach which from other comments sounds like it is probably deprecated now? (Perhaps this answer should have been split into two separate answers!) – Jon Schneider Aug 02 '17 at 21:02
89

I don't agree with the "you should only be interested in testing the external interface" philosophy. It's a bit like saying that a car repair shop should only have tests to see if the wheels turn. Yes, ultimately I'm interested in the external behavior but I like my own, private, internal tests to be a bit more specific and to the point. Yes, if I refactor, I may have to change some of the tests, but unless it's a massive refactor, I'll only have to change a few and the fact that the other (unchanged) internal tests still work is a great indicator that the refactoring has been successful.

You can try to cover all internal cases using only the public interface and theoretically it's possible to test every internal method (or at least every one that matters) entirely by using the public interface but you may have to end up standing on your head to achieve this and the connection between the test cases being run through the public interface and the internal portion of the solution they're designed to test may be difficult or impossible to discern. Having pointed, individual tests that guarantee that the internal machinery is working properly is well worth the minor test changes that come about with refactoring - at least that's been my experience. If you have to make huge changes to your tests for every refactoring, then maybe this doesn't make sense, but in that case, maybe you ought to rethink your design entirely. A good design should be flexible enough to allow for most changes without massive redesigns.

Darrell Plank
  • 1,124
  • 7
  • 5
  • 21
    I'm afraid I still disagree with you. Treating each component as a black box allows modules to be swapped in/out without problems. If you have a `FooService` that has to do `X`, all you should care about is that it does indeed do `X` when requested. _How_ it does it shouldn't matter. If there are problems in the class not discernible through the interface (unlikely), it's still a valid `FooService`. If it's a problem that _is_ visible through the interface, a test on public members should detect it. The whole point should be that as long as the wheel turns properly, it can be used as a wheel. – Basic Oct 24 '12 at 16:41
  • 6
    One general approach is that if your internal logic is complicated enough that you feel it requires unit testing, perhaps it needs to be extracted into some kind of helper class with a public interface that can be unit tested. Then your 'parent' class can simply make use of this helper, and everyone can be unit tested appropriately. – Mir Feb 08 '13 at 23:50
  • 12
    @Basic: Completely wrong logic in this answer. Classic case when you need private method is when you need some code to be reused by public methods. You put this code to some PrivMethod. This method should not be exposed to public, but needs testing to assure that public methods, which rely on PrivMethod, can really rely on it. – Dima Apr 08 '13 at 13:45
  • 6
    @Dima Surely then if there's a problem with `PrivMethod`, a test on `PubMethod` which calls `PrivMethod` should expose it? What happens when you change your `SimpleSmtpService` to a `GmailService`? All of a sudden your private tests are pointing at code that no longer exists or perhaps works differently and would fail, even though the application may work perfectly as designed. If there's complex processing that would apply to both email senders, perhaps it should be in an `EmailProcessor` which can be used by both and tested separately? – Basic Apr 08 '13 at 14:47
  • 1
    @Basic - surely there should be separate unit tests for the public 'interface' and the class implementing that which also tests its own private members as described by @Dima. When you change the class to `GmailService` the interface unit tests should still pass as you have correctly pointed out. – miltonb Feb 18 '14 at 00:12
  • 2
    @miltonb We may be looking at this from different development styles. WRT the internals, I don't tend to unit test them. If there's a problem (as identified by interface tests), it's either easy to track down by attaching a debugger or the class is too complex and should be split up (with the public interface of the new classes unit tested) IMHO – Basic Feb 18 '14 at 00:49
  • 1
    -1 for not actually telling us **how** to unit test private methods. – Sam I am says Reinstate Monica Jul 24 '14 at 18:56
  • I agree. It would be nice to test the individual parts which is what unit testing is all about. Testing the interface is more integration testing, but that's another discussion. IMO, the best/easiest alternative out of all the answers is to test the public method multiple times for specific results. – goku_da_master Sep 16 '14 at 18:34
  • I agree. It's great to say FooService should return X but in reality it often isn't that simple. A private method that returns different values depending on its input params and is part of a 100 line public method should be tested as an individual **unit** – BritishDeveloper Nov 26 '14 at 10:42
  • 1
    If you are used to developing an application that uses other components but is never a component itself, then the 'make everything public' philosophy probably works. If you are in the real world of corporate stuff, we have several components that are used in both our app and other teams' apps. Other teams should do black box testing, as unit tests aren't meant to test 3rd party code. Your team should still test everything 1st party to the app, even if it's private (mock 3rd party stuff). You make things private so consumers can't muck with stuff, but you still have to test it. – ps2goat Feb 05 '15 at 18:03
  • 1
    @Basic, you're of course right - if the wheel works then it's a fine wheel. When it doesn't work is what testing is all about. I write some super complex mathematical algorithms like the Fortune algorithm for Voronoi Diagrams which have a simple public interface and TONS of complicated math going on below the surface in private functions. If all I'm told is "That's not a valid voronoi diagram" then I'm stuck. I need to test my distance function, my priority queue, my scheduling of events, classification of events, etc.. This is all, quite rightly, private but it's where the complexity is. – Darrell Plank Aug 18 '16 at 04:18
  • Regarding unit testing I tend to think about two approaches test-first and code-first being test-first the traditional one coming from TDD with the Red-Green-Refactor cycle. The code-first approach means,well, writing the code first and then writing the tests. How to know which lines of code have been touched by my unit tests? Check tools like NCrunch, it is a commercial product. In the next release of Visual Studio 2017, announced at the Connect 2016 event, this functionality will be part of VS. – jpchauny Nov 26 '16 at 14:47
52

In the rare cases I have wanted to test private functions, I have usually modified them to be protected instead, and the I have written a subclass with a public wrapper function.

The Class:

...

protected void APrivateFunction()
{
    ...
}

...

Subclass for testing:

...

[Test]
public void TestAPrivateFunction()
{
    APrivateFunction();
    //or whatever testing code you want here
}

...
Jason Jackson
  • 17,016
  • 8
  • 49
  • 74
  • 2
    You can even put that child class in your unit test file instead of cluttering up the real class. +1 for cunning. – Tim Abell Dec 07 '11 at 13:11
  • I always put all test related code in the unit tests project if possible. This was just psuedo-code. – Jason Jackson Dec 07 '11 at 17:15
  • 3
    This function is not private, its protected, the net result ... you made your code less secure / exposed to child types private functionality – War Dec 11 '15 at 14:55
21

I think a more fundamental question should be asked is that why are you trying to test the private method in the first place. That is a code smell that you're trying to test the private method through that class' public interface whereas that method is private for a reason as it's an implementation detail. One should only be concerned with the behaviour of the public interface not on how it's implemented under the covers.

If I want to test the behaviour of the private method, by using common refactorings, I can extract its code into another class (maybe with package level visibility so ensure it's not part of a public API). I can then test its behaviour in isolation.

The product of the refactoring means that private method is now a separate class that has become a collaborator to the original class. Its behaviour will have become well understood via its own unit tests.

I can then mock its behaviour when I try to test the original class so that I can then concentrate on test the behaviour of that class' public interface rather than having to test a combinatorial explosion of the public interface and the behaviour of all its private methods.

I see this analogous to driving a car. When I drive a car I don't drive with the bonnet up so I can see that the engine is working. I rely on the interface the car provides, namely the rev counter and the speedometer to know the engine is working. I rely on the fact that the car actually moves when I press the gas pedal. If I want to test the engine I can do checks on that in isolation. :D

Of course testing private methods directly may be a last resort if you have a legacy application but I would prefer that legacy code is refactored to enable better testing. Michael Feathers has written a great book on this very subject. http://www.amazon.co.uk/Working-Effectively-Legacy-Robert-Martin/dp/0131177052

Big Kahuna
  • 545
  • 4
  • 12
  • 21
    Completely wrong logic in this answer. Classic case when you need private method is when you need some code to be reused by public methods. You put this code to some PrivMethod. This method should not be exposed to public, but needs testing to assure that public methods, which rely on PrivMethod, can really rely on it. – Dima Apr 08 '13 at 13:45
  • Makes sense during initial development, but do you want tests for private methods in your standard regression suit? If so, if the implementation changes, it can break the test suite. OTOH, if your regression tests focus only on externally visible public methods, then if the private method breaks later, the regression suite should still detect the error. Then if necessary, you can dust off the old private test if needed. – Alex Blakemore Jul 09 '13 at 00:51
  • 10
    Disagree, you should be testing the public interface only, else why the need for private methods. Make them all public in that case and test all of them.If you're testing private methods you're breaking enscapulation. If you want to test a private method and it's used in multiple public methods then it should be moved to its own class and tested in isolation.All the public methods should then delegate to that new class.In that way you still have tests for the original class' interface and you can verify the behaviour hasn't changed and you have separate tests for the delegated private method. – Big Kahuna Jul 24 '13 at 13:35
  • @Big Kahuna - If you think there is no case where you need to unit test private methods you never worked with a big/complex enough project. Lots of times a public function like client specific validations end up with 20 lines just calling very simple private methods to make the code more readable but you still have to test each individual private method. Testing 20 times the public function will make it very difficult to debut when the unit tests fail. – Pedro.The.Kid Oct 27 '17 at 10:27
  • 1
    I work for a FTSE 100 company. I think I've seen several complex projects in my time, thank you. If you need to test to that level, then each private method as separate collaborators, should be tested in isolation because it implies they have individual behaviour that needs testing. The test for the main mediator object then just becomes a interaction test. It just test the correct strategy is being called.Your scenario sounds like the class in question is not following SRP. It does not have a single reason to change but 20 => SRP violation. Have a read of GOOS book or Uncle Bob. YMWV – Big Kahuna Nov 09 '17 at 19:17
16

Private types, internals and private members are so because of some reason, and often you don’t want to mess with them directly. And if you do, chances are that you’ll break later, because there is no guarantee that the guys who created those assemblies will keep the private/internal implementations as such.

But ,at times, when doing some hacks/exploration of compiled or third party assemblies, I have myself ended up wanting to initialize a private class or a class with a private or internal constructor. Or, at times, when dealing with pre-compiled legacy libraries that I can’t change - I end up writing some tests against a private method.

Thus born the AccessPrivateWrapper - http://amazedsaint.blogspot.com/2010/05/accessprivatewrapper-c-40-dynamic.html - it's is a quick wrapper class that’ll make the job easy using C# 4.0 dynamic features and reflection.

You can create internal/private types like

    //Note that the wrapper is dynamic
    dynamic wrapper = AccessPrivateWrapper.FromType
        (typeof(SomeKnownClass).Assembly,"ClassWithPrivateConstructor");

    //Access the private members
    wrapper.PrivateMethodInPrivateClass();
amazedsaint
  • 7,642
  • 7
  • 54
  • 83
13

Well you can unit test private method in two ways

  1. you can create instance of PrivateObject class the syntax is as follows

    PrivateObject obj= new PrivateObject(PrivateClass);
    //now with this obj you can call the private method of PrivateCalss.
    obj.PrivateMethod("Parameters");
    
  2. You can use reflection.

    PrivateClass obj = new PrivateClass(); // Class containing private obj
    Type t = typeof(PrivateClass); 
    var x = t.InvokeMember("PrivateFunc", 
        BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Public |  
            BindingFlags.Instance, null, obj, new object[] { 5 });
    
Unknown
  • 259
  • 1
  • 3
  • 9
  • Good answer, but for #1 your syntax is wrong. You need to declare an instance of `PrivateClass` first and use that. http://stackoverflow.com/questions/9122708/unit-testing-private-methods-in-c-sharp#15607491 – SharpC Nov 16 '15 at 18:53
10

I've also used the InternalsVisibleToAttribute method. It's worth mentioning too that, if you feel uncomfortable making your previously private methods internal in order to achieve this, then maybe they should not be the subject of direct unit tests anyway.

After all, you're testing the behaviour of your class, rather than it's specific implementation - you can change the latter without changing the former and your tests should still pass.

philsquared
  • 22,403
  • 12
  • 69
  • 98
  • I love the point about testing behavior rather than implementation. If you tie your unit tests to implementation (private methods), then the tests will become brittle and need to change when the implementation changes. – Bob Horn Jun 11 '17 at 23:29
9

There are 2 types of private methods. Static Private Methods and Non Static Private methods(Instance Methods). The following 2 articles explain how to unit test private methods with examples.

  1. Unit Testing Static Private Methods
  2. Unit Testing Non Static Private Methods
Adam Wenger
  • 17,100
  • 6
  • 52
  • 63
Venkat
  • 91
  • 1
  • 1
8

MS Test has a nice feature built in that makes private members and methods available in the project by creating a file called VSCodeGenAccessors

[System.Diagnostics.DebuggerStepThrough()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TestTools.UnitTestGeneration", "1.0.0.0")]
    internal class BaseAccessor
    {

        protected Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject m_privateObject;

        protected BaseAccessor(object target, Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType type)
        {
            m_privateObject = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject(target, type);
        }

        protected BaseAccessor(Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType type)
            :
                this(null, type)
        {
        }

        internal virtual object Target
        {
            get
            {
                return m_privateObject.Target;
            }
        }

        public override string ToString()
        {
            return this.Target.ToString();
        }

        public override bool Equals(object obj)
        {
            if (typeof(BaseAccessor).IsInstanceOfType(obj))
            {
                obj = ((BaseAccessor)(obj)).Target;
            }
            return this.Target.Equals(obj);
        }

        public override int GetHashCode()
        {
            return this.Target.GetHashCode();
        }
    }

With classes that derive from BaseAccessor

such as

[System.Diagnostics.DebuggerStepThrough()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TestTools.UnitTestGeneration", "1.0.0.0")]
internal class SomeClassAccessor : BaseAccessor
{

    protected static Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType m_privateType = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType(typeof(global::Namespace.SomeClass));

    internal SomeClassAccessor(global::Namespace.Someclass target)
        : base(target, m_privateType)
    {
    }

    internal static string STATIC_STRING
    {
        get
        {
            string ret = ((string)(m_privateType.GetStaticField("STATIC_STRING")));
            return ret;
        }
        set
        {
            m_privateType.SetStaticField("STATIC_STRING", value);
        }
    }

    internal int memberVar    {
        get
        {
            int ret = ((int)(m_privateObject.GetField("memberVar")));
            return ret;
        }
        set
        {
            m_privateObject.SetField("memberVar", value);
        }
    }

    internal int PrivateMethodName(int paramName)
    {
        object[] args = new object[] {
            paramName};
        int ret = (int)(m_privateObject.Invoke("PrivateMethodName", new System.Type[] {
                typeof(int)}, args)));
        return ret;
    }
Marcus King
  • 1,667
  • 3
  • 15
  • 20
5

On CodeProject, there is an article that briefly discusses pros and cons of testing private methods. It then provides some reflection code to access private methods (similar to the code Marcus provides above.) The only issue I've found with the sample is that the code doesn't take into account overloaded methods.

You can find the article here:

http://www.codeproject.com/KB/cs/testnonpublicmembers.aspx

Pedro
  • 12,032
  • 4
  • 32
  • 45
5

For anyone who wants to run private methods without all the fess and mess. This works with any unit testing framework using nothing but good old Reflection.

public class ReflectionTools
{
    // If the class is non-static
    public static Object InvokePrivate(Object objectUnderTest, string method, params object[] args)
    {
        Type t = objectUnderTest.GetType();
        return t.InvokeMember(method,
            BindingFlags.InvokeMethod |
            BindingFlags.NonPublic |
            BindingFlags.Instance |
            BindingFlags.Static,
            null,
            objectUnderTest,
            args);
    }
    // if the class is static
    public static Object InvokePrivate(Type typeOfObjectUnderTest, string method, params object[] args)
    {
        MemberInfo[] members = typeOfObjectUnderTest.GetMembers(BindingFlags.NonPublic | BindingFlags.Static);
        foreach(var member in members)
        {
            if (member.Name == method)
            {
                return typeOfObjectUnderTest.InvokeMember(method, BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, null, typeOfObjectUnderTest, args);
            }
        }
        return null;
    }
}

Then in your actual tests, you can do something like this:

Assert.AreEqual( 
  ReflectionTools.InvokePrivate(
    typeof(StaticClassOfMethod), 
    "PrivateMethod"), 
  "Expected Result");

Assert.AreEqual( 
  ReflectionTools.InvokePrivate(
    new ClassOfMethod(), 
    "PrivateMethod"), 
  "Expected Result");
Erick Stone
  • 809
  • 1
  • 8
  • 16
4

Declare them internal, and then use the InternalsVisibleToAttribute to allow your unit test assembly to see them.

James Curran
  • 101,701
  • 37
  • 181
  • 258
4

I tend not to use compiler directives because they clutter things up quickly. One way to mitigate it if you really need them is to put them in a partial class and have your build ignore that .cs file when making the production version.

swilliams
  • 48,060
  • 27
  • 100
  • 130
  • You would include the test accessors in a production version (to test compiler optimizations etc) but exclude them in a release version. But I'm splitting hairs & I upvoted this anyway because I think it's a good idea to put that stuff in a single place. Thanks for the idea. – CAD bloke Nov 06 '13 at 10:49
3

You should not be testing the private methods of your code in the first place. You should be testing the 'public interface' or API, the public things of your classes. The API are all the public methods you expose to outside callers.

The reason is that once you start testing the private methods and internals of your class you are coupling the implementation of your class (the private things) to your tests. This means that when you decide to change your implementation details you will also have to change your tests.

You should for this reason avoid using InternalsVisibleToAtrribute.

Here is a great talk by Ian Cooper which covers this subject: Ian Cooper: TDD, where did it all go wrong

cda01
  • 1,278
  • 3
  • 14
  • 25
3

Sometimes, it can be good to test private declarations. Fundamentally, a compiler only has one public method: Compile( string outputFileName, params string[] sourceSFileNames ). I'm sure you understand that would be difficult to test such a method without testing each "hidden" declarations!

That's why we have created Visual T#: to make easier tests. It's a free .NET programming language (C# v2.0 compatible).

We have added '.-' operator. It just behave like '.' operator, except you can also access any hidden declaration from your tests without changing anything in your tested project.

Take a look at our web site: download it for free.

3

I want to create a clear code example here which you can use on any class in which you want to test private method.

In your test case class just include these methods and then employ them as indicated.

  /**
   *
   * @var Class_name_of_class_you_want_to_test_private_methods_in
   * note: the actual class and the private variable to store the 
   * class instance in, should at least be different case so that
   * they do not get confused in the code.  Here the class name is
   * is upper case while the private instance variable is all lower
   * case
   */
  private $class_name_of_class_you_want_to_test_private_methods_in;

  /**
   * This uses reflection to be able to get private methods to test
   * @param $methodName
   * @return ReflectionMethod
   */
  protected static function getMethod($methodName) {
    $class = new ReflectionClass('Class_name_of_class_you_want_to_test_private_methods_in');
    $method = $class->getMethod($methodName);
    $method->setAccessible(true);
    return $method;
  }

  /**
   * Uses reflection class to call private methods and get return values.
   * @param $methodName
   * @param array $params
   * @return mixed
   *
   * usage:     $this->_callMethod('_someFunctionName', array(param1,param2,param3));
   *  {params are in
   *   order in which they appear in the function declaration}
   */
  protected function _callMethod($methodName, $params=array()) {
    $method = self::getMethod($methodName);
    return $method->invokeArgs($this->class_name_of_class_you_want_to_test_private_methods_in, $params);
  }

$this->_callMethod('_someFunctionName', array(param1,param2,param3));

Just issue the parameters in the order that they appear in the original private function

Damon Hogan
  • 552
  • 3
  • 14
3

I'm surprised nobody has said this yet, but a solution I have employed is to make a static method inside the class to test itself. This gives you access to everything public and private to test with.

Furthermore, in a scripting language (with OO abilities, like Python, Ruby and PHP), you can make the file test itself when run. Nice quick way of making sure your changes didn't break anything. This obviously makes a scalable solution to testing all your classes: just run them all. (you can also do this in other languages with a void main which always runs its tests as well).

rube
  • 31
  • 2
  • 1
    Although this is practical, it's not very elegant. This can create a bit of a mess of a code base and also doesn't allow you to separate out your tests from your real code. The ability to test externally opens up the ability to script automate testing instead of writing static methods by hand. – Darren Reid Jun 06 '11 at 10:32
  • This does not preclude you from testing externally...just call the static method however you like. The code base is also not messy...you name the method accordingly. I use "runTests", but anything similar works. – rube Jun 06 '11 at 21:44
  • Your right, it doesn't preclude from testing externally, however it does generate a lot more code,ie make the code base messy. Each class might have a lot of private methods to test which initialises it's variables in one or more of its constructors. To test, you are going to have to write at least as many static methods as there are methods to test, and the test methods may have to be large to initialise the right values. This would make the maintenance of code more difficult. As others have said, testing the behaviour of a class is a better approach, the rest should be small enough to debug. – Darren Reid Jun 06 '11 at 22:09
  • I use the same number of lines to test as anyone else (actually less as you'll read later). You don't have to test ALL your private methods. Just the ones which need testing :) You also don't need to test each one in a separate method. I do it with one call. This actually make the maintenance of the code LESS difficult, since all my classes have the same umbrella unit test method, which runs all the private and protected unit tests line by line. The entire test harness then calls that same method on all my classes and the maintenance all resides within my class - tests and all. – rube Jun 09 '11 at 00:11
  • If you are suggesting adding unit test code within the code/assembly that is to be tested, that is a bad idea for several reasons; the least of which is that it is a security risk. – Dave Black Jan 06 '23 at 20:29
2

Here is good article about unit testing of private methods. But I'm not sure what's better, to make you application designed specially for testing(it's like creating tests for testing only) or use reflexion for testing. Pretty sure most of us will choose second way.

Johnny_D
  • 4,592
  • 3
  • 33
  • 63
2

MbUnit got a nice wrapper for this called Reflector.

Reflector dogReflector = new Reflector(new Dog());
dogReflector.Invoke("DreamAbout", DogDream.Food);

You can also set and get values from properties

dogReflector.GetProperty("Age");

Regarding the "test private" I agree that.. in the perfect world. there is no point in doing private unit tests. But in the real world you might end up wanting to write private tests instead of refactoring code.

Carl Bergquist
  • 3,894
  • 2
  • 25
  • 42
  • 4
    Just for info, `Reflector` has been replaced by the more powerful `Mirror` in Gallio/MbUnit v3.2. (http://www.gallio.org/wiki/doku.php?id=mbunit:mirror) – Yann Trevin Feb 12 '10 at 09:36
2
CC -Dprivate=public

"CC" is the command line compiler on the system I use. -Dfoo=bar does the equivalent of #define foo bar. So, this compilation option effectively changes all private stuff to public.

Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
Mark Harrison
  • 297,451
  • 125
  • 333
  • 465
2

I use PrivateObject class. But as mentioned previously better to avoid testing private methods.

Class target = new Class();
PrivateObject obj = new PrivateObject(target);
var retVal = obj.Invoke("PrivateMethod");
Assert.AreEqual(retVal);
vsapiha
  • 166
  • 2
  • 6
1

Here's an example, first the method signature:

private string[] SplitInternal()
{
    return Regex.Matches(Format, @"([^/\[\]]|\[[^]]*\])+")
                        .Cast<Match>()
                        .Select(m => m.Value)
                        .Where(s => !string.IsNullOrEmpty(s))
                        .ToArray();
}

Here's the test:

/// <summary>
///A test for SplitInternal
///</summary>
[TestMethod()]
[DeploymentItem("Git XmlLib vs2008.dll")]
public void SplitInternalTest()
{
    string path = "pair[path/to/@Key={0}]/Items/Item[Name={1}]/Date";
    object[] values = new object[] { 2, "Martin" };
    XPathString xp = new XPathString(path, values);

    PrivateObject param0 = new PrivateObject(xp);
    XPathString_Accessor target = new XPathString_Accessor(param0);
    string[] expected = new string[] {
        "pair[path/to/@Key={0}]",
        "Items",
        "Item[Name={1}]",
        "Date"
    };
    string[] actual;
    actual = target.SplitInternal();
    CollectionAssert.AreEqual(expected, actual);
}
Chuck Savage
  • 11,775
  • 6
  • 49
  • 69
1

A way to do this is to have your method protected and write a test fixture which inherits your class to be tested. This way, you are nor turning your method public, but you enable the testing.

kiriloff
  • 25,609
  • 37
  • 148
  • 229
  • I don't agree with this one, because you will also allow your consumers to inherit from the base class and use the protected functions. This was somehting you wanted to prevent in the first place by making those functions private or internal. – Nick N. Nov 17 '15 at 12:21
1

1) If you have a legacy code then the only way to test private methods is by reflection.

2) If it is new code then you have the following options:

  • Use reflection (to complicated)
  • Write unit test in the same class (makes the production code ugly by having test code also in it)
  • Refactor and make the method public in some kind of util class
  • Use @VisibleForTesting annotation and remove private

I prefer the annotation method, simplest and least complicated. The only issue is that we have increased the visibility which I think is not a big concern. We should always be coding to interface, so if we have an interface MyService and an implementation MyServiceImpl then we can have the corresponding test classes that is MyServiceTest (test interface methods) and MyServiceImplTest (test private methods). All clients should anyway be using the interface so in a way even though the visibility of the private method has been increased it should not really matter.

anuj
  • 201
  • 5
  • 16
1

You could also declare it as public or internal (with InternalsVisibleToAttribute) while building in debug-Mode:

    /// <summary>
    /// This Method is private.
    /// </summary>
#if DEBUG
    public
#else
    private
#endif
    static string MyPrivateMethod()
    {
        return "false";
    }

It bloats the code, but it will be private in a release build.

Alex H
  • 1,424
  • 1
  • 11
  • 25
1

In my opinion you should only unit test your classe's public API.

Making a method public, in order to unit test it, breaks encapsulation exposing implementation details.

A good public API solves an immediate goal of the client code and solves that goal completely.

jpchauny
  • 386
  • 2
  • 9
  • This should be the right answer IMO. If you have lots of private methods then this is probably because you have a hidden class that you should break out into its own public interface. – sunefred Jan 23 '17 at 16:54
0

You could generate the test method for the private method from Visual studio 2008. When you create a unit test for a private method, a Test References folder is added to your test project and an accessor is added to that folder. The accessor is also referred to in the logic of the unit test method. This accessor allows your unit test to call private methods in the code that you are testing. For details have a look at

http://msdn.microsoft.com/en-us/library/bb385974.aspx

Sarath
  • 2,719
  • 1
  • 31
  • 39
0

Also note that the InternalsVisibleToAtrribute has a requirement that your assembly be strong named, which creates it's own set of problems if you're working in a solution that had not had that requirement before. I use the accessor to test private methods. See this question that for an example of this.

Community
  • 1
  • 1
Chuck Dee
  • 690
  • 1
  • 19
  • 29
  • 3
    No, the `InternalsVisibleToAttribute` does **not** *require* that your assemblies be strongly named. I currently use it on a project where that is not the case. – Cody Gray - on strike Apr 13 '11 at 00:24
  • 1
    To clarify this: "Both the current assembly and the friend assembly must be unsigned, or both must be signed with a strong name." - From MSDN – Hari Apr 04 '12 at 07:43
0

In C# you can use the code I provide below. Though I think that unit testing private methods should be done only if absolutely needed. I have come across a few cases where I felt it was warranted. Here are some C# methods that I created in a UnitTestBase class I inherit my UnitTest classes from (you could also put it in a static "helper" class). HTH

protected internal static TResult? InvokePrivateInstanceMethod<TType, TResult>(string methodName, object?[]? methodArguments = null, params object?[]? constructorArguments)
{
    var classType = typeof(TType);
    var instance = Activator.CreateInstance(classType, constructorArguments);
    var privateMethodInfo = classType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
                                        .FirstOrDefault(m => m.IsPrivate &&
                                            m.Name.Equals(methodName, StringComparison.Ordinal) &&
                                            m.ReturnType.Equals(typeof(TResult)));
 
    if (privateMethodInfo is null)
    {
        throw new MissingMethodException(classType.FullName, methodName);
    }

    var methodResult = privateMethodInfo.Invoke(instance, methodArguments);
    if (methodResult is not null)
    {
        return (TResult)methodResult;
    }

    return default;
}

protected internal static async Task<TResult?> InvokePrivateInstanceMethodAsync<TType, TResult>(string methodName, object?[]? methodArguments = null, params object?[]? constructorArguments)
{
    var classType = typeof(TType);
    var instance = Activator.CreateInstance(classType, constructorArguments);
    var privateMethodInfo = classType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
                                        .FirstOrDefault(m => m.IsPrivate &&
                                            m.Name.Equals(methodName, StringComparison.Ordinal) &&
                                            m.ReturnType.Equals(typeof(Task<TResult>)));
            
    if (privateMethodInfo is null)
    {
        throw new MissingMethodException(classType.FullName, methodName);
    }

    var methodResult = privateMethodInfo.Invoke(instance, methodArguments);
    if (methodResult is not null)
    {
        return await (Task<TResult>)methodResult;
    }

    return default;
}
Dave Black
  • 7,305
  • 2
  • 52
  • 41
-1

For JAVA language

Here, you can over-ride a particular method of the testing class with mock behavior.

For the below code:

public class ClassToTest 
{
    public void methodToTest()
    {
        Integer integerInstance = new Integer(0);
        boolean returnValue= methodToMock(integerInstance);
        if(returnValue)
        {
            System.out.println("methodToMock returned true");
        }
        else
        {
            System.out.println("methodToMock returned true");
        }
        System.out.println();
    }
    private boolean methodToMock(int value)
    {
        return true;
    }
}

Test class would be:

public class ClassToTestTest{

    @Test
    public void testMethodToTest(){

        new Mockup<ClassToTest>(){
            @Mock
            private boolean methodToMock(int value){
                return true;
            }
        };

        ....    

    }
}
Amit Kaneria
  • 5,466
  • 2
  • 35
  • 38