Click here to Skip to main content
15,890,438 members
Articles / Programming Languages / C#

Extension Methods and Unit Testing in VS2008

Rate me:
Please Sign up or sign in to vote.
4.17/5 (12 votes)
4 Nov 2007CPOL8 min read 50.2K   133   39   4
Create some useful Extension Methods using .NET 3.5, then test your new methods using the built-in unit testing functionality in VS2008 Professional.

Unit Tests in VS2008

Contents

Introduction

This article is going to be using some of the new features available with the new Visual Studio 2008 Beta 2 Professional edition. Download it now if you haven't already. I have been using it for almost 3 months now, and I have not looked back. I now use it for all my HTML and CSS editing, including writing this very article. Not only does it have a host of new features, but you get performance improvements too, and even though it is still a beta version, I have had absolutely no problems or crashes whilst using it.

Some New VS2008 Pro Features

  • Multi-Targeting - targets different .NET Framework versions.
  • Split View WYSIWYG - view both design and source at the same time.
  • JavaScript intellisense and debugging.
  • Improved CSS support.
  • Nested master pages.
  • Unit Testing.

Some New .NET 3.5 Features

I am not going to explain what some of the new features are, but rather leave it to Scott Guthrie and let his blog posts do the talking.

Extension Methods

One of the features that caught my eye straight away was Extension Methods. Extension methods "allow developers to add new methods to the public contract of an existing CLR type, without having to sub-class it or recompile the original type." They also make other powerful features, like LINQ, possible. I also then realized that it is now possible to "add" functionality to the existing framework classes, for example, the System.String class. I have always had a class of static string utility methods that I use in all my projects and applications. It is a part of a utils class library that I have built and grown over the years while using .NET. So this was the perfect opportunity to rewrite my utilities class library using version 3.5 and take advantage of (and learn) the new features. I have already started doing this, and I am blogging about it as I go.

First Example

An extremely simple (and useless!) example of an Extension Method can be seen in the following code:

C#
namespace Utils.MyExtensions
{
     public static class JunkExtensions
     {
          public static string ToSomethingElse(this string input)
          {
                return input.PadLeft(10);
          }
     }
}

Please note that your Extension Methods must be defined inside a non-generic static class. Now, to use the Extension Method, include the namespace in your code:

C#
using Utils.MyExtensions;

...and your new Extension Method is now available to you, as you can see in the intellisense:

Extension Method in intellisense

When NOT To Use Them

I will be the first to admit that Extension Methods can be both useful and powerful, but when is enough enough? Scott Guthrie says in his post: "As with any extensibility mechanism, I'd really caution about not going overboard creating new extension methods to begin with. Just because you have a shiny new hammer doesn't mean that everything in the world has suddenly become a nail!" You couldn't say it any better than that. Listen to Scott - he knows best. You must not convert all your static utility methods to Extension Methods. What is the point? Do you really want to see a string class that has hundreds of methods available, but you only use 10% of them most of the time? Obviously not.

When To Use Them

You should only convert your most reusable, everyday static methods. Don't just create an Extension Method because you can; create one because you know it will help you code smarter. I create Extension Methods that, I think, improve and extend the framework, and that I feel should also be part of the framework. When I find myself asking the question: "But why didn't they include this method in the framework?", a new Extension Method usually follows shortly after.

Also, make Extension Methods that are just wrappers around your utility methods. This way, the utility code and the Extension Method code can be kept separate, so the developer has the choice to use the Extension Methods or not. This can easily be explained with an example utility method:

C#
public static string CutEnd(string input, int length)
{
     if (IsEmpty(input)) return input;
     if (input.Length <= length) return string.Empty;
     return input.Substring(0, input.Length - length);
}

and here is my Extension Method:

C#
public static string CutEnd(this string input, int length)
{
     return Utils.Strings.CutEnd(input, length);
}

This gives the developer the freedom he/she wants, whereby the Extension Method or the static method can be used. Also, only one set of tests needs to be done for both methods.

Strange Behavior

Now, I would have thought that creating an Extension Method that checks for nulls is pretty pointless. My thinking was: "how could I check for null if the object is null - won't I get a NullReferenceException?" Well, I tested it, and apparently no - you won't get the exception. Here's the Extension Method:

C#
public static bool IsNullOrEmpty(this string input)
{
     if (input == null) return true;
     return input.Length == 0;
}

Here's some code to test it:

C#
string str = null;
if (!str.IsNullOrEmpty())
{
     Console.Write(str);
}

This code runs fine - no problems! Very strange indeed, but at the same time, useful. More can be read about this at http://diditwith.net.

Testing Extension Methods

When developing any code that will be reused again and again (including Extension Methods), writing tests for that code becomes a necessity. This is to ensure the code is both reliable and bug free. When creating a reusable framework that is reused on every project and also likely to change a number of times in its lifetime, testing becomes an absolute requirement! The only smart way to utilize these types of tests is by writing Unit Tests. Unit tests allows you to keep a set of tests that you can run at any time, over and over again, to check for all use-case scenarios. So, when you make a change to a utility method, run the unit tests for that method to make sure it still does what you expect. There are many unit testing frameworks out there, including NUnit which is an Open Source framework written in C#. You can also purchase and/or download add-ins for Visual Studio to allow for unit testing within the IDE, but these are no longer required. There is now built-in Unit Testing functionality in VS2008 Pro. Woohoo!

Unit Testing in VS2008 Professional

With a few simple clicks of the mouse, you can create unit tests for code that you have written. Let's do that for our Extension Method:

  1. Click the Test menu, then 'New Test'.
  2. Select the 'Unit Test Wizard' option and click OK.
  3. Unit Test Wizard

  4. Enter the name of your new test project.
  5. Select the methods you wish to test and click OK.
  6. Select Methods

It's that simple! We have now created a new project called UtilsTests that contains all our tests for the Extension Methods we just created:

Unit Test Project

Now all you need to do is customize the tests to suite your needs. Here is the generated test code:

C#
/// <summary>
///A test for ToSomethingElse
///</summary>
[TestMethod()]
public void ToSomethingElseTest()
{
     string input = string.Empty; // TODO: Initialize to an appropriate value
     string expected = string.Empty; // TODO: Initialize to an appropriate value
     string actual;
     actual = JunkExtensions.ToSomethingElse(input);
     Assert.AreEqual(expected, actual);
     Assert.Inconclusive("Verify the correctness of this test method.");
}

As you can see, it intelligently looks at the input parameters of the method and generates the test for you. All you need to do now is change the input and the expected output, then remove the Assert.Inconclusive line, add a few tweaks, and you have a working unit test. This is what the test should look like now:

C#
[TestMethod()]
public void ToSomethingElseTest()
{
     string input = "abc123";
     string expected = "      abc123";
     string actual = input.ToSomethingElse();
     Assert.AreEqual(expected, actual);
}

Obviously, a unit test is only as good as the coder who wrote it, so make sure your unit tests are extensive. Actually, be more extensive than you usually would, and take into account even the simplest cases. In fact, be paranoid when you write your unit test. This way, you will be sure your tests cover every angle.

Now run your tests by clicking Test > Run > All Tests in Solution:

Run your Unit Tests

..and see the result in VS2008:

Unit Test Results

As you can see from the screenshot, not all our tests passed. We now need to delve into the code and see why. So, like you would normally do as a VS developer, place a break point into your failed test code. But this time, instead of just running your tests, choose to run them in Debug mode by clicking Test > Debug > All Tests in Solution:

Debug Unit Test

Now you can step through your code and see why the test is failing:

Debugging a Unit Test

Conclusion

So we have run through a very simple example of what Extension Methods are and how to write unit tests to test them. I hope this article has created some interest in the new features available in VS2008, as they have dramatically helped me code smarter. I use the unit test features daily with my new utilities project written for the .NET Framework 3.5. For example, every day I seem to change or add functionality to my string utils class, and what better way to know and trust that my changes work than by having a set of unit tests that I can run at a click of a button.

Go check out my String Utils class written in .NET 3.5 with a few handy Extension Methods. There you can download the source which includes the full unit tests for the methods.

History

  • 4 Nov. 07: Version 1 submitted.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
South Africa South Africa
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralStatic Utility Method and Extension Methods Pin
BigPMcCoy18-Jun-08 7:04
BigPMcCoy18-Jun-08 7:04 
Questionwhat are the risks with extending a class with additional methods Pin
Alexis Rzewski7-Jun-08 0:59
Alexis Rzewski7-Jun-08 0:59 
Just because YOU CAN doesn't mean it is necessarily a good thing to do. Extending a class's API with additional signatures means diverting the original designer's intent with your own custom design, additionally polluting the namespace. Case in point: the DateTime class. It is well known to all that it doesn't have much information of month names. That's because it is found in GregorianCalendar, when the culture info is United States and using the English language. So, getting today's month name is a bit cumbersome, having to use many separate classes just to get that info. Ever tried populating a dropdown listbox with english month names, January to December? not so obvious... So, the developer might be tempted on extending the DateTime class with MonthNameArray that returns string[] (an array of strings). Fine. That was in one departmental project. In another departmental project, they might be doing their own custom extensions to the DateTime class. Then, developers migrate from one project to another, and bring with them their own personal extensions, and add them again to the new project's DateTime class. OK, now, pressing the dot shows IntelliSense retrieving HUNDREDS of new methods, some may be named PrintMMDDYYYY, PrintLongMonthDayLongYear, etc etc. Just imagine when a manager wants to merge these two apps. You might just have two separate methods, similarly named, that might just do almost the same thing. Or, what about when you "reuse" some code, but this code is invoking methodds that don't exist in your DateTime class... Guess what: you will be forced to extend your DateTime class with their extensions. This is a new feature that is being allowed by the compiler. People think it is cool. Great. Now the gates are open. Before going gung-ho on these extensions, consult with other developers that have used them in other programming environments, and ask them about the pros and cons, specially after a couple of years on a project. You will see there is a price in future maintenability. My advice: add extensions to a class only when there is no other way to do what you want to do. If there is a different pattern or helper class that achieves the same goal, go for that solution. If you inherited a DLL-ized component for which you do not have the source code, and the API framework that you are using requires that this DLL-ized component, in order to be usable, needs to understand the message being sent to it named "DisplayValueName" and it takes a signature of "string, int", then, go ahead, and extend that DLL-ized component with public void DisplayValueName (string param1, string param2)
AnswerRe: what are the risks with extending a class with additional methods Pin
BigPMcCoy18-Jun-08 9:32
BigPMcCoy18-Jun-08 9:32 
GeneralUnit testing in VS2008 Pin
si6186-Nov-07 13:25
si6186-Nov-07 13:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.