How do you unit test private methods?
Asked Answered
P

32

511

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?

Paule answered 30/10, 2008 at 15:49 Comment(8)
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. msdn.microsoft.com/en-us/library/ms184807%28VS.90%29.aspxScamander
This seems a near duplicate of stackoverflow.com/questions/34571/….Indium
The questioner may not be using visual studioQuant
Don't unit test internals: blog.ploeh.dk/2015/09/22/unit-testing-internalsPolish
Possible duplicate of How do I test a class that has private methods, fields or inner classes?Indium
The Private Accessors are deprecated in Visual Studio as of 2012.Recipience
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.Mathre
Related post - Unit testing private methods in C#Jaal
W
127

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

Witenagemot answered 30/10, 2008 at 15:52 Comment(10)
Yuck. This gets compiled into your released assemblies.Epithelioma
@Epithelioma - couldn't one use #if DEBUG around the InternalsVisibleTo attribute to make it not apply to release code?Estate
@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)Epithelioma
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?Devan
I don't understand, how does that even solve the answer one single bit.Debase
@Epithelioma 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.Crass
The linked article in the answer no longer existsAtheism
@Epithelioma - Forgive me for my ignorance, but what's so bad about that attribute being compiled into your released assemblies?Fortnight
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.Recipience
@Epithelioma 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.Shoal
K
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).
Karyotype answered 30/10, 2008 at 15:54 Comment(11)
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.Eclogue
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.Neurogenic
Well, the tests are supposed to break if you change the implementation. TDD would mean changing the tests first.Tameika
@Tameika - 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.Dragoon
@Tameika 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 changesSorb
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.Keverne
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.Lauryn
@Keverne 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?Sverre
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.Fionnula
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.Plexor
"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.Shoal
W
127

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

Witenagemot answered 30/10, 2008 at 15:52 Comment(10)
Yuck. This gets compiled into your released assemblies.Epithelioma
@Epithelioma - couldn't one use #if DEBUG around the InternalsVisibleTo attribute to make it not apply to release code?Estate
@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)Epithelioma
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?Devan
I don't understand, how does that even solve the answer one single bit.Debase
@Epithelioma 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.Crass
The linked article in the answer no longer existsAtheism
@Epithelioma - Forgive me for my ignorance, but what's so bad about that attribute being compiled into your released assemblies?Fortnight
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.Recipience
@Epithelioma 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.Shoal
G
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[] {/* ... */} );
Groomsman answered 29/10, 2010 at 13:50 Comment(6)
How do you invoke private static methods?Sorosis
Private accessors are deprecated in Visual Studio 2012.Aldas
The accessor method of testing Private Methods is being deprecated from VS 2011 onwards. blogs.msdn.com/b/visualstudioalm/archive/2012/03/08/…Bugeye
Reading the docs found on Microsoft's website here I don't see any mention of the PrivateObject class being deprecated. I'm using MSVS 2013 and it works as expected.Univalent
@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."Univalent
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!)Mechanical
G
91

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.

Godinez answered 19/10, 2010 at 6:34 Comment(11)
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.Hyperbolism
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.Nomothetic
@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.Lucey
@Lucey 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?Hyperbolism
@Hyperbolism - 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.Twobit
@Twobit 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) IMHOHyperbolism
-1 for not actually telling us how to unit test private methods.Preglacial
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.Jurel
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 unitSufficient
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.Janie
@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.Godinez
L
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
}

...
Linguistic answered 30/10, 2008 at 16:4 Comment(3)
You can even put that child class in your unit test file instead of cluttering up the real class. +1 for cunning.Doralin
I always put all test related code in the unit tests project if possible. This was just psuedo-code.Linguistic
This function is not private, its protected, the net result ... you made your code less secure / exposed to child types private functionalityLilytrotter
U
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

Ursa answered 24/10, 2012 at 16:30 Comment(5)
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.Lucey
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.Jurist
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.Ursa
@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.Lucilelucilia
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. YMWVUrsa
O
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();
Oppugnant answered 25/5, 2010 at 7:44 Comment(0)
Y
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 });
    
Yeo answered 27/3, 2012 at 7:51 Comment(1)
Good answer, but for #1 your syntax is wrong. You need to declare an instance of PrivateClass first and use that. stackoverflow.com/questions/9122708/…Beachlamar
R
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.

Remote answered 30/10, 2008 at 15:55 Comment(1)
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.Logicize
E
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
Emend answered 22/7, 2011 at 12:32 Comment(3)
Provide some examples, not only give a linkDruse
Looks ugly. No intellisense. Bad solution from MS. I am in shock !Accra
Easiest way to test private static methodsGiffin
O
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;
    }
Ofilia answered 30/10, 2008 at 16:10 Comment(2)
The gen'd files only exist in VS2005. IN 2008 they're generated behind the scenes. And they're an abmomination. And the associated Shadow task is flaky on a build server.Marengo
Also accessors were deprecated in VS2012-2013.Basement
L
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

Lepidote answered 4/11, 2008 at 18:35 Comment(0)
F
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");
Fullrigged answered 16/12, 2015 at 18:32 Comment(0)
S
4

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

Salinger answered 30/10, 2008 at 15:51 Comment(1)
I don't like using InternalsVisibleTo because I made the method private for a reason.Isolative
I
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.

Isolative answered 30/10, 2008 at 15:59 Comment(1)
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.Condensable
A
3
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.

Argil answered 31/10, 2008 at 7:44 Comment(3)
What is this? Does this apply to Visual Studio?Brogue
"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. ha-ha!Argil
In Visual Studio, set a define in your build environment.Argil
P
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.

Pears answered 1/5, 2010 at 17:24 Comment(0)
S
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).

Sibie answered 6/6, 2011 at 9:24 Comment(5)
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.Wry
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.Sibie
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.Wry
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.Sibie
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.Unexpected
B
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

Bezique answered 3/7, 2014 at 0:49 Comment(0)
H
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

Hasson answered 16/7, 2015 at 19:34 Comment(0)
I
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.

Immutable answered 24/8, 2009 at 7:12 Comment(1)
Just for info, Reflector has been replaced by the more powerful Mirror in Gallio/MbUnit v3.2. (gallio.org/wiki/doku.php?id=mbunit:mirror)Nial
I
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.

Inlaw answered 11/4, 2012 at 15:14 Comment(0)
A
2

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.

Alby answered 22/9, 2014 at 18:34 Comment(1)
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.Cockchafer
R
2

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.

Richburg answered 18/6, 2015 at 15:40 Comment(0)
C
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);
Camp answered 21/4, 2017 at 11:57 Comment(0)
A
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);
}
Amatory answered 17/5, 2012 at 18:5 Comment(0)
A
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.

Animation answered 28/9, 2015 at 7:36 Comment(0)
T
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.

Thesda answered 26/11, 2016 at 14:33 Comment(1)
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.Polyptych
A
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

Arquebus answered 28/5, 2010 at 20:39 Comment(0)
A
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.

Arlinda answered 12/4, 2011 at 20:8 Comment(2)
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.Grunenwald
To clarify this: "Both the current assembly and the friend assembly must be unsigned, or both must be signed with a strong name." - From MSDNEyelet
U
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;
}
Unexpected answered 6/1, 2023 at 23:21 Comment(0)
B
-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;
            }
        };

        ....    

    }
}
Bridgework answered 29/1, 2018 at 19:35 Comment(1)
This question is tagged .net - as such this is not an answer so should be deleted.Gayomart

© 2022 - 2024 — McMap. All rights reserved.