ChatGPT解决这个技术问题 Extra ChatGPT

How do you unit test private methods?

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?

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.aspx
This seems a near duplicate of stackoverflow.com/questions/34571/….
The questioner may not be using visual studio

J
Jeroen Heijmans

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:

If the method you'd like to test is really worth testing, it may be worth to move it into its own class. 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).


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.
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.
Well, the tests are supposed to break if you change the implementation. TDD would mean changing the tests first.
@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.
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.
R
Raedwald

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


Yuck. This gets compiled into your released assemblies.
@Jay - couldn't one use #if DEBUG around the InternalsVisibleTo attribute to make it not apply to release code?
@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)
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?
@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.
P
Pang

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[] {/* ... */} );

How do you invoke private static methods?
Private accessors are deprecated in Visual Studio 2012.
The accessor method of testing Private Methods is being deprecated from VS 2011 onwards. blogs.msdn.com/b/visualstudioalm/archive/2012/03/08/…
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.
@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."
D
Darrell Plank

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.


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.
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.
@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 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?
@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
J
Jason Jackson

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
}

...

You can even put that child class in your unit test file instead of cluttering up the real class. +1 for cunning.
I always put all test related code in the unit tests project if possible. This was just psuedo-code.
This function is not private, its protected, the net result ... you made your code less secure / exposed to child types private functionality
B
Big Kahuna

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


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.
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.
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 - 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.
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
a
amazedsaint

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();

U
Unknown

Well you can unit test private method in two ways

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"); 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 });


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/…
p
philsquared

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.


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.
A
Adam Wenger

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.

Unit Testing Static Private Methods Unit Testing Non Static Private Methods


Provide some examples, not only give a link
Looks ugly. No intellisense. Bad solution from MS. I am in shock !
Easiest way to test private static methods
M
Marcus King

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;
    }

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.
Also accessors were deprecated in VS2012-2013.
P
Pedro

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


J
James Curran

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


I don't like using InternalsVisibleTo because I made the method private for a reason.
s
swilliams

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.


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.
c
cda01

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


E
Erick Stone

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");

L
Ludovic Dubois

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.


r
rube

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).


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.
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.
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.
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.
D
Damon Hogan

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


C
Carl Bergquist

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.


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)
J
Johnny_D

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.


j
jpchauny

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.


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.
v
vsapiha

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);

S
Samuel Liew
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.


What is this? Does this apply to Visual Studio?
"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!
In Visual Studio, set a define in your build environment.
C
Chuck Savage

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);
}

k
kiriloff

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.


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.
a
anuj

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.


A
Alex H

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.


S
Sarath

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


C
Community

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.


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.
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