Thursday, April 26, 2007

Unit Testing Private Methods

When writing unit tests, I frequently find myself wanting to test private methods. I used to think there were only three approaches to solving this problem.

  1. Test the private method indirectly through some other, public method that invokes it.
    • Pros: Keeps your class interface clean and doesn't compromise your OO design
    • Cons: You may not be able to test all of the cases you'd like through the public method, and your test results may be affected by the code in the public method.

  2. Make the private method protected and create a derived class in your test project that exposes the method publicly.
    • Pros: Allows you test the method directly
    • Cons: Compromises the encapsulation of your initial design, requires writing more test classes.

  3. Refactor the private method into some other class that exposes it publicly.
    • Pros: Doesn't require more test code, you may actually end up with more well-factored design
    • Cons: You probably don't want to make this code public, isn't that why it was private in the first place?
So, given these options, I went with #2. I've written a lot of tests like this, but it's a chore to implement these wrapper classes in your test code, and I always thought there must be a better way. Fortunately, if you're programming in .Net, there is:
  1. Use reflection to invoke the private method directly
    • Pros: Totally rocks.
    • Cons: Invoking the private method looks a little funky
Kudos to Michael Kelly for showing me this approach. Now that I've seen this in action, its the only way I deal with this case. Here's a sample implementation to get you started:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

public class TestReflector
{
public static T InvokeNonPublicMethod<T>( string methodName, object obj,
params object[] parameters )
{
MethodInfo methodInfo =
obj.GetType().GetMethod( methodName, BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.Static);
if ( methodInfo == null )
{
throw new ApplicationException( "Private method not found for: '" +
methodName + "'." );
}
return (T)methodInfo.Invoke( obj, parameters );
}
}


With that in place, it's very simple to use:

MyClass myClass = new MyClass();
string string1 = "abcdef";
string string2 = "123456";
string result = TestReflector.InvokeNonPublicMethod<string>(
"MyPrivateMethod", myClass, string1, string2 );


This code will support any non-public method with any number of parameters and any return type, except void. If you do need void support, its a simple adaptation of this code. Hope this helps!

Wednesday, April 25, 2007

Unit Testing With Mock Objects - Slides and Sample Code

Thanks to everyone who attended my mock objects talk at Innotech today, I hope it wasn't too obvious that it was the first time I've presented at a conference ;-) As promised, I've posted my slides and source code here. Sorry about the ads, but Blogger doesn't support file uploads and this site was the best I could find on short notice. If you're here for the links, here you go:

If you have any additional resources you'd like to share, let me know and I'll post them here.

Thanks again,
John

Sunday, January 07, 2007

Online Mii Maker

Have some time to waste? Try this!

Thursday, December 07, 2006

5 Things I Look for in a Job

1. Passion - Is the team passionate about the craft of software development? Is the company? People who love software breed enthusiasm, while the apathetic, "it's just a job" types can suck the life out of any room.

2. Purpose - What impact will this software have on its users? Working on tax management software is considerably less appealing than developing a website that allows people to donate to charity.

3. Respect - You've just entrusted me to develop your server applications, don't prohibit me from browsing Flickr. It's insulting. Occasionally, a cup of coffee and a random diversion are exactly what I need to solve a hard problem.

4. Opportunity - How can this company change the world? What part might I play in that? Not everyone is in this game for the money.

5. Comfort - Is there good coffee? Decent chairs? Windows? A company that creates an uplifting work environment is far more likely to attract top talent than a company that keeps its developers in the basement.

Tuesday, December 20, 2005

My Photo Collection

I just finished uploading a bunch of my favorite photos to Flickr. Photography has been a hobby of mine for a few years now, and I figured that anyone reading this might also be interested in my work. Check it out!

Friday, September 23, 2005

OEF Entrepreneurship Award

Last night, my company, Eleven Wireless, attended the Oregon Entrepreneurs Forum's awards dinner. We were nominated for the Development Stage Company of the Year award, and, as luck would have it, we won! Needless to say, we were all surprised and delighted, and we spent the rest of the night celebrating.

It's great to see our sacrifices, hard work, and potential recognized by Portland's investment community. The company has been around for about three years now, and it just keeps getting better. I think we have great opportunities ahead of us, and we're in for one hell of a ride.

Tuesday, September 13, 2005

XPDX Rocks

I just got home from my first XPDX meeting, and I have to say I was very impressed. Arlo Belshee's presentation on Promiscuous Pairing was great, and there were many interesting discussions before, during, and after the presentation.

As a member of a team that moved to XP (Extreme Programming, for the non-nerds in the audience) nearly a year ago, I am interested in seeing what other teams have done with XP, and what results they've had. I've found that, while XP has a few essential core practices, every team that implements XP does so in a unique fashion. This is not a bad thing, and, in fact, is a part of the methodology.

The great thing about this group is that folks with extremely diverse backgrounds can share their thoughts and experiences with development in general, and XP in particular. At this point, you're probably thinking, "What the hell else did you expect from an XP user group? Recipes?" Well, what I find particularly interesting is that XP evolves by design. This is sometimes criticized as loose definition, but, when you get a bunch of people exchanging their experiences with XP in the same room, you see that its strength lies in its flexibility.

It empowers a team to adjust its process to fit into its working environment without degrading into chaos. Over time, variations of the process are exchanged within the community, and the most successful variations are canonized in the process definition itself. Groups like XPDX accelerate this evolution, and it was great to see it in action. If you live in the Portland area and are interested in software development, check it out. You won't be disappointed.