Unit Testing In Enterprise Library

Tuesday, February 15, 2005

Let me start by pointing to Tom Hollander, who is looking for feedback and input to build the next version of Enterprise Library.

I now return you to my irregularly scheduled ramblings...

Unit testing is here to stay. The only questions about unit testing revolve around the details. Do we test non-public types and methods? Do we use mock objects? I’m always interested in seeing real unit testing code from other projects to understand what decisions others have made. (For an intro to unit testing, see: “Improve the Design and Flexibility of Your Project with Extreme Programming Techniques”).

Enterprise Library uses the NUnit testing framework. It will be interesting to see how easily this will port to the VS 2005 unit testing framework (or even if the tests are ported to 2005, considering the unit testing framework may only be included with the Team System version of Visual Studio 2005). I know I’m chiming in late, but I hope we see unit testing in all versions of Visual Studio.

Enterprise Library includes unit tests in the same assembly as the classes being tested. Tests are surrounded with an #ifdef, presumably to keep them out of production builds and also to allow the library to compile on systems without NUnit.

The unit tests do access members with internal scope.

Unit testing code in EntLib is not in short supply. Here is a snippet from ConnectionStringFixture.cs:

   44 [Test]

   45 public void CanGetCredentialsFromRealSqlDataClass()

   46 {

   47    string initialConnectionString =

   48       String.Format("server=localhost; database=JoeRandom; uid={0}; pwd={1}; ;",

   49          userName, password);

   50    this.connectionString = new ConnectionString(initialConnectionString, userIdTokens, passwordTokens);

   51    Assert.AreEqual(userName, this.connectionString.UserName);

   52    Assert.AreEqual(password, this.connectionString.Password);

   53 }

The ConnectionStringFixture class has 10 tests in all:

InvalidOperationExceptionThrownWhenConnectionStringIsNull()
EmptyCredentialsReturnedForEmptyConnectionString()
CanGetCredentialsFromRealSqlDataClass()
CreateNewConnectionStringTest()
CreateNewConnectionStringTest()
CanAddCredentialsToConnectionStringThatDoesNotHaveThem()
CanSetUserIdAndPasswordInConnectionStringThatAlreadyHasOne()
RemovingCredentialsFromConnectionStringWithoutThemIsOk()
WillRemoveCredentialsFromConnectionString()
NullTests()

The overall style and naming conventions stick to accepted practices for writing unit tests. One issue up for debate is the testing of internal methods. I like the approach. Internal members are good candidates for testing since they often form the surface area of an API one layer beneath the public façade. After a short conversation with Rocky this week - I realize there is at least one person who doesn’t agree.

What do you think? (Regarding ‘what to test that is’ – I know some of you think about a lot of things).

Coming soon: Mock classes - and why they make me uncomfortable.


Comments
haacked@gmail.com (Haacked) Tuesday, February 15, 2005
In principle, I'm for unit testing internal methods. In practice I am not as I prefer to have my unit tests in a separate assembly than the code being tested. I can write more later on why that is, but basically it's easier to maintain and I think it forces you to think about the public API, where changes are more influential and less likely to occur.
<br>
<br>By testing internal methods, unit tests might have more churn as internal methods might change often. The purpose of encapsulation is not to have to worry about the internal implementation details and to isolate client code from internal changes.
<br>
<br>However, I am all for testing protected members by creating a Test class that inherits the class containing the protected member.
Darrell Tuesday, February 15, 2005
I think I will test internal methods if it helps me to code better or faster. If it slows me down and doesn't improve quality, then I won't. :)
Mark Levison Tuesday, February 15, 2005
We keep our test assemblies separate from our live code, so until we start using Whidbey we can't test internal methods. However if I could I would test most, especially ones that feel close to the surface of the API.
John Wednesday, February 16, 2005
Public interface only. Keep tests in seperate library. Use Debug.Assert for private bits.
Bill Tuesday, February 22, 2005
Scott - have you checked out the Quality Control stuff in 2005 yet?
Scott Tuesday, February 22, 2005
Yeah - a little bit. To be honest the stuff it codegens sort of hurts my eyes - I don't like all the wrapper classes and such it creates to test private members.
<br>
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!