Los Techies : Blogs about software and anything tech!

Testing Private & Protected Members of a Class


In my last blog post, someone asked me you can write unit tests for a private or protected method.  I gave part of the response in a comment, but I need to give a more detailed description.

Focus on the public API of your system

First and foremost, I focus on testing the public API.  You should be able to test all of the code branches in your private methods by adequately testing the public methods in your system.  Using tools like NCover can help you analyze how well your tests are actually testing your system.  I don’t try to get 100% coverage, but I typically have above 80% as a normal target.

Testing Protected Members

There are times when you do need to test protected members of a class.  If you are inheriting from a class that you do have the source code to (like say Controller) and you override a protected method, it is possible to test that.  While it should be possible to test protected member through the public api, it is relatively simple to do it and doesn’t really break any encapsulation rules in your application.

It is actually very easy.  All you need to do is create a test class that inherits from you and add a public method that call the protected method in question.  Here is an example.

public class ClassWithProtectedMember
    {
        
protected int UltimateQuestionAnswer() { return 42; }
    }

    
public class ProtectedMemberAccessor : ClassWithProtectedMember
    {
        
public int ExecuteUltimateQuestionAnswer(){
            
return base.UltimateQuestionAnswer();}
    }
    [
TestFixture]
    
public class ProtectedMemberSpecs {

        [
Test]
        
public void should_give_us_the_answer_to_life_universe_and_everything()
        {
            
var wrapper = new ProtectedMemberAccessor();
            
Assert.That(wrapper.ExecuteUltimateQuestionAnswer(),Is.EqualTo(42));
        }
    \

This is a very simple and straightforward approach, but is very effective in testing some hidden members in you system.

Kick It on DotNetKicks.com
Posted Aug 28 2009, 12:48 AM by jcteague
Filed under: ,

Comments

pablo wrote re: Testing Private & Protected Members of a Class
on 08-28-2009 3:29 AM

I asked you this question yesterday and in the meantime @KentBeck replied to my tweet about that too.

His words: twitter.com/.../3579860805

@pablogl i only test public methods. if a private method is complex enough to need testing, it generally needs its own object.

In other words, if the private/protected method is really so important that you have to test it, then perhaps we are violating the Single Responsibility Principle.

jcteague wrote re: Testing Private & Protected Members of a Class
on 08-28-2009 10:19 AM

@pablo

That's absolutely true.  The times when I needed to test a protected member I'm sure I was violating SRP. The most recent need for me to do so was overrided a member on the Controller class.  I'm not sure I had a way to do in a way without violating SRP since I do not own the Controller class.

ctasada wrote re: Testing Private & Protected Members of a Class
on 08-29-2009 1:16 PM

You can find a different approach for the same problem here:

ctasada.blogspot.com/.../junit-how-to-test-your-private-methods.html

jcteague wrote re: Testing Private & Protected Members of a Class
on 08-29-2009 2:13 PM

@ctasada

yes, reflection is an option.  MSTest actually creates a helper class for you that gives you access to all of your methdods for you.

However I agree with the comment pablo made that if they are really that complex, chances are you're missing an abstraction somewhere in your design.

Jason Baker wrote re: Testing Private & Protected Members of a Class
on 08-29-2009 4:40 PM

Interesting post.  I've outlined a few ways of looking at the "how do I test private methods" question here:  jasonmbaker.wordpress.com/.../enemies-of-test-driven-development-part-i-encapsulation

jcteague wrote re: Testing Private & Protected Members of a Class
on 08-29-2009 10:30 PM

@Jason

I liked your post.  It reminded me of something I should have mentioned in my original post.  I guess that means I should write a new one huh?

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

Enter the numbers above:
Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems