|
|
Comments and Discussions
|
|
 |

|
I found this article both interesting and useful.
|
|
|
|
|

|
Since Google still pulls up this fantastic article when searching for private method unit tests, I though I give a little update on the topic: When testing methods that have the private/protected protection level, just call the class that includes the protected method with the _Accessor extension and the method is free for testing. E.g. myClass will be called as myClass_Accessor. Btw: the wizard for unit tests will automatically include this extension for protected methods.
|
|
|
|

|
The point of Test Driven Development is to atomically test your code. As you create functionality, even private functionality, it should be driven by tests.
I honestly don't see how anyone can argue for NOT testing private functions. You aren't doing TDD if you ignore the pattern sometimes and follow it other times. By not following TDD at all times you negate the entire purpose of TDD. Just like if you half washed your car you still have a dirty car and if you half tested your code you still untested code.
The argument that private functions aren't part of your interface so shouldn't be tested ignores the whole purpose of TDD which is to test every bit of your code, functional block by functional block, and only after it passes move on. You aren't just testing your interface you are testing your code.
Also the argument that changing private functions will break your tests is non-sense since you shouldn't be changing your code without changing the test first to match the logical change you want. Your test SHOULD fail then you can change your code to make the test pass. Just like when you wrote the test in the first place.
And finally you can use the PrivateObject() class in VS 2010 to test private functions so there is no excuse not to.
|
|
|
|
|

|
Thanks the code and sample helped me. Again thanks
|
|
|
|

|
Very clear, pragmatic, polite and useful.
Thank you.
--
Arialdo Martini
|
|
|
|

|
HI...
I need
Need Some Code Example of Ajax IN Aps.NET
|
|
|
|

|
I complied and started using this code, it's wonderful. I ran into one snag, which was quickly fixed by making an addition to your code. I often test for expected exceptions, most notably ArgumentNull and ArgumentOutOfRange. However since the Helper class uses Reflection any thrown exceptions within in the non-public methods get wrapped in a System.Reflection.TargetInvocationException and therefore my tests failed because the expected exception type was not met.
I suggest changing RunMethod to the following to make testing for Expected Exceptions a bit easier. You could apply this try-catch logic to all of your tests that expect exceptions, but it seems more efficient to let the Helper class handle it, and avoid the repetition.
private static object RunMethod(System.Type t, string strMethod, object objInstance, object[] aobjParams, BindingFlags eFlags) {
MethodInfo m;
try {
m = t.GetMethod(strMethod, eFlags);
if (m == null) {
throw new ArgumentException("There is no method '" + strMethod + "' for type '" + t.ToString() + "'.");
}
object objRet = m.Invoke(objInstance, aobjParams);
return objRet;
} catch(System.Reflection.TargetInvocationException tie){
if(tie.InnerException != null){
throw tie.InnerException;
}else {
throw tie;
}
} catch {
throw;
}
}
Thanks for the artcicle.
JB
|
|
|
|

|
I also found that I needed a change to work with non-public methods that have output or reference parameters. Changing the object[] parameter to ref param makes both possible.
public static object RunStaticMethod(System.Type t, string strMethod, ref object[] aobjParams) {
BindingFlags eFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
return RunMethod(t, strMethod, null, ref aobjParams, eFlags);
}
public static object RunInstanceMethod(System.Type t, string strMethod, object objInstance, ref object[] aobjParams) {
BindingFlags eFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
return RunMethod(t, strMethod, objInstance, ref aobjParams, eFlags);
}
private static object RunMethod(System.Type t, string strMethod, object objInstance, ref object[] aobjParams, BindingFlags eFlags) {
MethodInfo m;
try {
m = t.GetMethod(strMethod, eFlags);
if (m == null) {
throw new ArgumentException("There is no method '" + strMethod + "' for type '" + t.ToString() + "'.");
}
object objRet = m.Invoke(objInstance, aobjParams);
return objRet;
} catch(System.Reflection.TargetInvocationException tie){
if(tie.InnerException != null){
throw tie.InnerException;
}else {
throw tie;
}
} catch {
throw;
}
}
|
|
|
|

|
Great article, very usefull! But i did have a problem when I called a private function with different signatures, I got a System.Reflection.AmbiguousMatchException That is why i made another method to get the method using its name + signature. When the System.Reflection.AmbiguousMatchException is thrown I try again now looping through the methods to find the method with the right signature. That is handled by the method GetMethodUsingSignature. public static object RunPrivateMethod(System.Type t, string methodName, object objInstance, ref object [] aobjParams) { MethodInfo m = null; BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic; try { m = t.GetMethod(methodName, bindingFlags); } catch (System.Reflection.AmbiguousMatchException ex) { //Console.WriteLine("AmbiguousMatchException for method: " + methodName + "\tTry again using GetMethodUsingSignature" ); m = GetMethodUsingSignature(t, methodName, aobjParams, bindingFlags); } if (m == null) { throw new ArgumentException("There is no method '" + methodName +"' for type '" + t.ToString() + "'."); } object objRet = m.Invoke(objInstance, aobjParams); return objRet; } private static MethodInfo GetMethodUsingSignature(System.Type type, string methodName, object[] aobjParams, BindingFlags bindingFlags) { MethodInfo m = null; MethodInfo[] myArrayMethodInfo = type.GetMethods(bindingFlags); for(int i=0;i<myArrayMethodInfo.Length;i++) { MethodInfo myMethodInfo = (MethodInfo) myArrayMethodInfo[i]; if (myMethodInfo.Name == methodName) { if (myMethodInfo.GetParameters().Length == aobjParams.Length) { int counter = 0; ParameterInfo [] methodSignarure = myMethodInfo.GetParameters(); foreach (object parameter in aobjParams) { if (parameter.GetType() != methodSignarure[counter].ParameterType & (methodSignarure[counter].ParameterType.IsByRef & parameter.GetType() != methodSignarure[counter].ParameterType.GetElementType())) { break; } counter++; } m = myMethodInfo; break; } } } return m; }
-- modified at 7:28 Sunday 23rd April, 2006
|
|
|
|

|
I think there can be more transparent approach:
If we have an utility that generates a wrapper assembly (simillar to wrapper assembly for COM) for another assembly where all items became public (that uses reflection) and for tests we just use these (proxy) classes and methods.
This approach is also good if you want to have all tests in separate assembly. In such way you can transperently test internal classes.
If somebody knows such utility I'd like to use it.
|
|
|
|

|
As far as I know the new Visual Studio 2005 Team Edition generates wrappers for private methods / classes.
BTW: Internal classes can now be tested by using the 'InternalsVisibleTo' attribute in the AssemblyInfo class.
Michael
|
|
|
|

|
You are right. But i am still using .Net 1.1.
Anyway my approach is the nearest to approach in VS 2005. So using this strategy will be good when you will migrate to 2005.
|
|
|
|

|
I've actually developed such a tool and was surprised to find this thread when I was doing some more searches before I post my implementation.
http://www.futureware.biz/downloads/rpg20060122.zip
I haven't wrote any external documentation for it yet, but the XML documentation should be thorough enough. You should find the following in the zip file:
1. A console application which has the generator (rpg.exe).
2. A sample class library which has the internal classes.
3. A sample unit test assembly which has the generates proxies for these classes and some test cases.
All what you need to do to generate proxies for all internal classes in an assembly is:
rpg.exe myassembly.dll
This will generate files like MyFirstProxy.cs, MySecondProxy.cs (for classes MyFirst and MySecond).
Looking forward for your feedback.
Regards,
Victor
Victor Boctor
http://www.futureware.biz[^]
|
|
|
|

|
Thanks for the great article!
Is there a similar way to test private classes?
I am writing a library which contains some private helper classes to hold internal data structures. It does not make sense to expose them publicly, but nevertheless, they should be tested. The approach you describe fails when you want to pass 'typeof(ClassLibrary1.MyObject)' into RunInstanceMethod, because I cannot access the private type in my test project. So far I am stuck with #if DEBUG making the classes public.
|
|
|
|

|
Yes, there is!
Type privateType = Type.GetType("TopNamespace.SubNameSpace.ContainingClass+NestedClass,MyAssembly");
object obj =
UnitTestUtilities.Helper.RunInstanceMethod(
privateType, "MyPrivateMethod",
objInstance, new object[3] {"Hello",
new DateTime(2004,05,24), 2.1});
|
|
|
|

|
That's helpful, but you don't show to get objInstance if you're dealing with a private class. I added another method to the Helper class that will create that object instance for you based on the privateType: public static object GetObjectInstance(System.Type t) { BindingFlags eFlags = BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance; return t.InvokeMember(null, eFlags, null, null, null); } Now you can call the RunInstanceMethod. FWIW
|
|
|
|

|
I'm wondering if there is any way to extend this to being able to call a private constructor? What I'm trying to do is test a singleton class which needs to be reset between tests because otherwise the class may have some state information left over from the previous test.
Previously I would have just added a #if #endif block so that the test could use a public constructor.
So far my attempts at calling a private constructor look like this:
public static object RunConstructor(System.Type type, params object[] parameters)
{
BindingFlags bindingAttr =
BindingFlags.CreateInstance | BindingFlags.Static |
BindingFlags.Public | BindingFlags.NonPublic;
int len = parameters.Length;
Type[] types = new Type[len];
ParameterModifier[] modifiers = new ParameterModifier[len];
for (int i=0; i<len;i++)
{
types[i] = parameters[i].GetType();
modifiers[i] = new ParameterModifier(0);
}
ConstructorInfo constructor = type.GetConstructor(bindingAttr, null,
types, modifiers);
return constructor.Invoke(bindingAttr, null, parameters, null);
}
Any ideas?
Cada uno es artifice de su ventura
WDevs.com - Open Source Code Hosting, Blogs, FTP, Mail and Forums
|
|
|
|

|
Good point. Offhand I'm not sure, although I'll keep my eyes open about it.
Tim
Tim Stall
MCAD.Net
http://timstall.dotnetdevelopersjournal.com/
|
|
|
|

|
This does it for me (just change BindingFlags.Static to BindingFlags.Instance):
Type type = typeof(TypeWithPrivateCtor);
Type[] ctorParams = new Type[0];
ConstructorInfo info = type.GetConstructor(BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic, null, ctorParams, null);
object obj = info.Invoke(null);
Cheers!
Nick
|
|
|
|

|
But instead of all that faffing about with inherited classes and reflection what I do is create the private method, then create a debug block like this:
class MyClass
{
private int MyPrivateMethod(string someParam)
{
}
#if DEBUG
public int TEST_MyPrivateMethod(string someParam)
{
return MyPrivateMethod(someParam);
}
#endif
}
Then in my unit tests I can call the TEST_... method and for other code I know that any method beginning TEST_... won't be available in the release build, so I just don't use it. Visual Studio is also quite good at helping as it will grey out the text in the DEBUG block if I've got the current build set to DEBUG.
It is also possible to create your own blocks and have a special unit test build.
Also, I ensure that the test method is named exactly the same as the original method but with a "TEST_" prefix on it. Ever since I started taking the Cradle-to-grave naming concept seriously I cannot believe how much time I've saved by not having to think about what such and such a method or variable is called.
You mention in the article: "This only works in Debug mode." Is that really such a big deal? If it is, then there is nothing to stop you defining a UNITTEST block and having a release build with the additional tests in it.
You also wrote: "This is procedural and not object-oriented. We would need to wrap the individual methods in both the production code and unit tests." I don't see why you are wrapping the methods in the production code. The compiler will strip out the wrappers in production code as they won't be used in the production code. I also don't see how it "is procedural"
And: "This alters the SUT by adding the public method wrappers." I don't see this as a problem. No more of a problem that inheriting and putting the wrapper in the derived class, or creating a wrapper using reflection.
Cada uno es artifice de su ventura
WDevs.com - Open Source Code Hosting, Blogs, FTP, Mail and Forums
|
|
|
|

|
Hey Colin, Thanks for the feedback. Keep in mind that I initially started using #if DEBUG … #endif. It does work, and is certainly better than no test at all. > You mention in the article: "This only works in Debug mode." Is that really such a big deal? Why not take the approach that lets you run tests on the Release build - the same code shipped to the client? In your sample, you’ve done all the work to create a test for MyPrivateMethod, and while you can run it in debug mode guaranteeing some degree of success (if it passes in Debug, it will probably pass in Release), you can’t run it in Release. > I don't see why you are wrapping the methods in the production code. > And: "This alters the SUT by adding the public method wrappers." The gist of my point is that you need to physically alter the source code file by (1) wrapping creating public TEST_xxx methods, and (2) wrapping these methods in #if DEBUG … #endif (or something similar like “UNITTEST). These alterations do not add any feature to the client; they are used only to assist in testing. > I also don't see how it "is procedural" It encloses #if DEBUG … #endif directives around each method/group of methods instead of applying them at the object level. Perhaps it would be clearer to think of it as “not object oriented”. Tim Tim Stall MCAD.Net http://timstall.dotnetdevelopersjournal.com/
|
|
|
|

|
TimStall wrote:
if it passes in Debug, it will probably pass in Release
Ah... Okay - I take your point, they may be some subtle difference between debug and release that isn't obvious or immediately apparent.
I orignally wrote:
I don't see why you are wrapping the methods in the production code
TimStall responded:
The gist of my point is that you need to physically alter the source code file by (1) wrapping creating public TEST_xxx methods, and (2) wrapping these methods in #if DEBUG … #endif (or something similar like "UNITTEST"). These alterations do not add any feature to the client; they are used only to assist in testing.
I guess point 1 will be mitigated in C# 2.0 and the introduction of partial classes - no longer need to modify the original source file as these wrappers can be added in a secondary source file.
As for point 2: I see that they don't add anything to the client, but why is the client caring about unit tests?
TimStall wrote:
Perhaps it would be clearer to think of it as “not object oriented”.
I think this is a point that will sink in over the course of the next few days, but for the moment I cannot see a problem creating a #if UNITTEST block next to a method to expose it publicly in a unit testing build (i.e. Effectively a debug or release type build with unit testing wrappers in it). The wrapper is simply has an identical signature (save for the public exposure and the "TEST_" prefix) and does nothing but call the private method.
Anyway - It might make more sense when I get a chance to play with these ideas over the weekend.
Cada uno es artifice de su ventura
WDevs.com - Open Source Code Hosting, Blogs, FTP, Mail and Forums
|
|
|
|

|
> I cannot see a problem creating a #if UNITTEST block next to a method to expose it publicly
While I agree that it works, one reason that I switched is because it requires writing a bunch of extra test code. The approach I outlined requires only a single utility method once - not a new wrapper for each private method.
Tim Stall
MCAD.Net
http://timstall.dotnetdevelopersjournal.com/
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
This article explains some theory behind testing/not testing private methods, and then provides and walks through a downloadable code sample to demonstrate these testing techniques.
| Type | Article |
| Licence | |
| First Posted | 1 Mar 2005 |
| Views | 210,592 |
| Bookmarked | 116 times |
|
|