How do you unit test private methods?

前端 未结 30 1447
无人及你
无人及你 2020-11-22 06:44

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 coul

相关标签:
30条回答
  • 2020-11-22 07:28

    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

    0 讨论(0)
  • 2020-11-22 07:29

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

    0 讨论(0)
  • 2020-11-22 07:30

    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();
    
    0 讨论(0)
  • 2020-11-22 07:31

    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

    0 讨论(0)
  • 2020-11-22 07:31

    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.

    0 讨论(0)
  • 2020-11-22 07:31

    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.

    0 讨论(0)
提交回复
热议问题