Calling private methods from Unit Tests

 

A classical problem with
unit tests is the need for calling non-public methods of the code to test.
Indeed, we generally prefer isolating unit tests code in dedicated tests
assemblies. And non-public code cannot be called from outer assemblies.

 

We can distinguish
between internal and private methods. Concerning internal code elements, you can harness
the System.Runtime.CompilerServices.InternalsVisibleToAttribute
to make internal types/methods/fields visible from unit tests. This is clean
and I hope this tips is now widely adopted.

 

Concerning private methods we are stuck with
reflection to invoke them from unit tests. This is unfortunate, both because it
requires more work on tests and because we lose strong-typing verification
while compiling tests.

 

The idea I would like to
propose here is to use some NDepend capabilities to be able to test private methods trough strong typed tests. The
astute is to use a dedicated attribute to transform a private method into an internal
method for which, NDepend warns if the method is called from outside its class. You can use your own
attribute to do so, or the predefined attribute NDepend.CQL.IsOnlyUsedByTestAttribute that you can find in the
redistributable NDepend.CQL.dll. Then
you need the following CQL rule
to be warned if there are some methods tagged that could not be private. Here
the CQL condition CouldBePrivate can
be understood as not used from outside its
class
:

Normal
0

21

false
false
false

FR
X-NONE
X-NONE

MicrosoftInternetExplorer4

 

// <Name>Method tagged with IsOnlyUsedByTestAttribute must not be used from outside
its class</Name>

WARN IF Count > 0 IN SELECT METHODS WHERE

  HasAttribute “NDepend.CQL.IsOnlyUsedByTestAttribute” AND

  !CouldBePrivate

 

To make this work
properly, don’t forget to not reference unit tests assemblies from your NDepend
project. Else NDepend could not consider such method as CoulBePrivate.

Also you might already have
a rule to care for optimal encapsulation,
meaning you want to make sure that all methods not used from outside their
classes are declared private. In such case don’t forget to tweak this rule
slightly to avoid being informed of method tagged with IsOnlyUsedByTestAttribute.

 

Normal
0

21

false
false
false

FR
X-NONE
X-NONE

MicrosoftInternetExplorer4

 

// <Name>Methods that could be declared as ‘private’ in C#,  ‘Private’ in
VB.NET</Name>

WARN IF Count > 0 IN SELECT METHODS WHERE

  CouldBePrivate AND

  !HasAttribute “NDepend.CQL.IsOnlyUsedByTestAttribute “

 

We apply this trick on our own code and I find it clean because:

  • It works: no more reflection, no more weak typing, no more dilemma.
  • It is not intrusive: as mentioned the
    attribute can be your own attribute, not related to NDepend. In the future, you might be able to use
    another way than NDepend to harness information carried by such attribute.
  • It is documentation: the attribute tells the developer reading the code that the tagged method is private and it is called from automatic tests. This is an extra information that can be precious to avoid breaking some test code unexpectedly.
  • It is active documentation: without the attribute, NDepend will tell you that you need it since the method satisfies the CQL condition CouldBePrivate and with the rule mentioned above, you want to avoid such method.
  • It classifies all occurrences of private methods called by unit tests: you just need to ask for methods tagged with the concerned attribute.

 

I
intentionally didn’t mention so far the hot debate about if tests should call or
not private methods
.
Personally I try to avoid this practice as much as I can, both because 100% of
the feature of a class should be testable from the outside and because private
things are supposed to be implementation details, highly subject to change. But it does happen sometime
that testing directly private methods help writing easier tests. In such cases
I estimate being pragmatic is allowed. It is so counter-productive to spend 30 minutes writing
a single unit test that recovers all the messy states needed to cover a tricky
scenario, generally implemented though one or two lines of code in a if clause of a private method.

 

 

This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Damokles

    What about using Publicize to Create Private Accessors: http://msdn.microsoft.com/en-us/library/bb514191.aspx

  • http://www.4444444444444444409hcvw0wvhm9p8hemc.com Preved

    I do agree with you. http://111111111tv0m0vttqay-7vt-vt0-mqva.com sdrafx 222222 [url=http://33333333333333333sfgwet.com]333333[/url]Simple superb.

  • Hussein Mehanna

    I think that being able to access your private methods is a neat trick.

    I personally use it extensively to simulate special\corner scenarios quickly without having to invest in mock objects. Specially when I am working with legacy code that hasn’t been designed to allow the usage of mock objects.

    We use another way to access private methods. What we do is after the assembly we want to test is built, using reflection we create another assembly that turns all the non public fields\properties\methods etc into public. We call this publicizing the dll.

    Saves us some work.

  • http://www.NDepend.com Patrick Smacchia

    Thanks all for participating in the debate,

    As Bernhard underlined, “All debate of whether or not to test private methods aside”, this is indeed not the debate.

    It seems that this practice is not appealing to most of you. We found it pretty convenient though and I wanted to share the trick. Our main usage is to avoid spending hours to cover one or two lines to jump from 99% coverage to 100% coverage. I don’t feel good having almost 100% coverage but not exactly 100% and I don’t think it is productive investing hours in test/refactoring to cover very few lines.

  • Bernhard Hofmann

    All debate of whether or not to test private methods aside; I still think this is a bad practice. It might work if what you are building contains your libraries and ALL CONSUMERS. But if you are building for a third party, your query for usage outside the tests is pointless.

    I’m not “feeling” this at all. Sorry.

  • http://jamespeckham.com james peckham

    In regards to your type safety consider something like this using inheritance.

    public class Cat
    {
    private string name;
    }

    you’d write something to inherit from that to make it testable

    public class TestCat : Cat
    {
    public string TestName
    {get{/* do your reflection in here to get name */}}
    }

  • Sandor Davidhazi

    You say it can get complicated when you have to bring the object to a certain state through public methods to be able to test every line of a private method. That is true, however, with your solution a programmer would have to keep attributes up to date in every class AND check if they are used correctly with a third party tool. So, I don’t think we are better with either solution from the standpoint of the amount of work and attention needed. However, there is a very important standpoint, which decides to test private methods independently or not.

    Unit test are also meant to verify your code, for example to discover, if there is dead code which never gets reached from your public methods. It is very easy to get lost in a long private method and write up something, that never gets evaluated, but there is something fairly important going on in there.

    And generally, you are required to write test for those public methods anyway, so why not extend those tests to test that class thoroughly, including all cases of private methods? And it is even easier to verify your work: just check your coverage report.

  • Steve Py

    Sorry, but it is just a smell if you feel you need unit tests for private implementation. Unit tests or behavioural tests should be around public or “internally public” implementation. The internals of private implementation should be fully testable through the behaviours of the public interface. Otherwise you have code that’s doing too much, or something equally sinister that needs attention.

    I can’t think of any time I have felt that the only way I could test a block of code was to hook into the private methods directly… At least not in situations where it would have been much more effective to re-factor the code.

    Granted, this does take an investment in time, but if you’ve got time to scrutinize cyclic-namespaces and the like, you should be able to justify cleaning up smelly bits as well. (Though I’m not sure if NDepend does *that* for us just yet. ;)

  • http://www.NDepend.com Patrick Smacchia

    Richard, yes I am aware of these classes + tooling that make them more usable. This is still using reflection (test code weakly typed) + potential security issue (CAS permission) + you cannot see in your code which private method is tested directly (fragile code, very easy to break test).

    >IMO the easiest for the long term would be to refactor the class into two classes.

    I didn’t say anything different, read my previous answers. The fact is that development resources are not infinite and in the real world choices have to be done.

  • alwink

    IMO the easiest for the long term would be to refactor the class into two classes. If you have to test a specific private method, that shouldn’t be used anywhere else, it looks like a hack to me. If it isn’t important enough to split up, don’t make the effort to test it.

    And I would love to see a blog post that doesn’t read like a NDepend advertisement…

  • http://twitter.com/zerobugbounce Richard Lowe

    Just as a side note, in the Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll Assembly, there are two reflection helper classes called ‘PrivateObject’ and ‘PrivateType’ which assist specifically in calling the private parts of your classes and types, respectively. I encourage you to check them out!

  • http://www.NDepend.com Patrick Smacchia

    >It is just a code smell, when you want to call your private methods. It means your class has two (at least) responsibilities.

    Dmitry, I don’t disagree, refactoring to make the class more testable is indeed a cleaner option than hard testing only public methods which is indeed a cleaner option than testing private class.

    The problem is cost vs. clean, I estimate that sometime it is worth hooking some private methods, this is my opinion based on my real world programming, because the 2 other options cost ‘a lot’ unfortunately and resources are not infinite.

    >” .. blah blah blah we have a problem .. blah blah blah .. And here comes NDepend to save the day .. :)

    Khaja, I explained my position with NDepend in the answers of my last posts. Concerning these 2 particular problems exposed (spaghetti code + testing private methods) I estimate that NDepend brings innovative solutions to the table that are worth being mentioned and debated. You are highly welcome to submit your own solutions and participate to the debate. Pure noise as you do is not added value and will be removed from now.

  • http://minhajuddin.com Khaja Minhajuddin

    For the last couple of posts, I am seeing a pattern emerge out of your blog posts. It seems to go this way:
    ” .. blah blah blah we have a problem .. blah blah blah .. And here comes NDepend to save the day .. :)

  • http://codebetter.com/members/Dmitry-Novoselov/default.aspx Dmitry Novoselov

    It is just a code smell, when you want to call your private methods. It means your class has two (at least) responsibilities.

    When I start willing to call some private method/s I split the original class and then test public interface of the new class.

  • http://www.NDepend.com Patrick Smacchia

    Sean, Tormod, at the end of the post I explain that:
    - one should avoid calling private method from tests
    - but sometime you have the choice between:
    1) Spending a long time (> 30mn) writing a very complicated test to cover a very particular case burried in a private method
    2) Hook directly the private method and test the very particular test
    In such situation, I found 2) more appropriate and pragmatic. Of course 1) would be more clean but much more costly also.

  • http://schambers.lostechies.com Sean Chambers

    I have to agree with Tormod here.

    Why would you ever want to directly test a private method? Private methods are going to be invoked by the public methods which should have unit tests. I know you referenced that you personally don’t utilize this practice, therefore I don’t understand why you would explain that people can achieve this using attributes and interal keywords.

    As Tormond stated, a private method is an implementation concern which shouldn’t be known outside the relevant class.

  • Tormod

    Well, why would you want to invoke private methods from unit tests?
    The private methods are run from public methods which are run from your tests.

    Assuming that you originally coded that private method in order to make a failing unit test pass, this problem should not occur.

    The private method is an implementation detail which you should be able to refactor at will.