Tuesday, May 27, 2008

TDD: Test internal methods the correct way

The aim: write a comprehensive suite of unit tests for a library we are creating.

Create a library project named Lib, which contains a class named StrExt, which contains a public method Tidy and an internal method IsBad. The implementation is as follows ...

namespace Lib
{
  public class StrExt
  {
   public string Tidy(string s)
   {
       if (IsBad(s) == false)
           return s.Trim();
       else
                return null;
   }

   internal bool IsBad(string s)
   {
       return s == null;
   }
 }
}
To test the above class, create a test project, call it Lib.Tests. In it, create the following test method to test the public method Tidy(string)...
    [TestMethod]
   public void Tidy_ReturnsCorrectValue()
   {
       string inStr = "test ";
       string expOutStr = "test";
       string actualOutStr = lib.Tidy(inStr);
       Assert.AreEqual(expOutStr, actualOutStr);
   }
This will work fine.

But what if we wanted to (and we should) test the internal method IsBad(string). Notice that the intellisense in the capture below does not display IsBad. This is obviously because the method IsBad, is declared internal to the Lib assembly and is therefore not visible to other assemblies such as Lib.Tests.

image

Writing tests for internal methods is a very common scenario. People often use convoluted techniques like Reflection etc to invoke the internal method. An easier and the correct solution is to use InternalsVisibleToAttribute as follows ...

using System.Runtime.CompilerServices;

[assembly: InternalsVisibleToAttribute("Lib.Tests")]

namespace Lib
{
  public class StrExt { ... /* No change in this class */ }
}
This makes the internal methods of the class visible to the named assembly. Now notice the intellisense ...

image

You can now test IsBad(string) in your test class as follows ...
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Lib
{
 [TestClass]
  public class Lib_UnitTests
  {
   private StrExt lib = new StrExt();

   [TestMethod]
   public void Tidy_ReturnsCorrectValue()
   {
       string inStr = "test ";
       string expOutStr = "test";
       string actualOutStr = lib.Tidy(inStr);
       Assert.AreEqual(expOutStr, actualOutStr);
   }

   [TestMethod]
   public void IsBad_ReturnsTrueForNullString()
   {
       string inStr = null;
       bool result = lib.IsBad(inStr);
       Assert.IsTrue(result);
   }
 }
}
Look ma, no reflection!

Links for Week 20, 2008

Coding > .Net

Coding > .Net > LINQ

Monday, May 26, 2008

Extension Methods: Why you need to check for nulls?

Extension methods is a good feature. For example, consider the following extension method ...

  public static string[] ToWordArray( this string str )
 {
     return str.Split( ' ' );
 }
Usage ...
    string s1 = "This is a sentence";
    string[] words = s1.ToWordArray();
Looking at the usage, it appears to be an instance method call. But this is misleading, when compiled, calls to 'ToWordArray' extension method are transformed by the compiler into static method calls. So the usage above is translated into ...
    string s1 = "This is a sentence";
    string[] words = string.ToWordArray(s1);
So, since this is not an instance call, the run-time will allow null reference to go through, resulting in NullReference exceptions. See the following example ...
    string s2 = null;
    string[] words = s2.ToWordArray(); // will result in exception
To avoid such issues, extension methods must test for null parameters. The above extension should be correctly implemented as below ...
  public static string[] ToWordArray( this string str )
 {
     if ( str == null )
         return null;
     else if ( str.Length == 0 )
         return new string[ 0 ];
     else // empty string has 0 words
            return str.Split( ' ' );
 }

Friday, May 23, 2008

WaitHandle

Description

Used to synchronize threads' activities

Class Hierarchy

  • WaitHandle
    • Mutex
    • Semaphore
    • EventWaitHandle
      • EventWaitHandle
        • AutoResetEvent
        • ManualResetEvent

Mutex: provides exclusive access to a resource. It uses more system resources than Monitor class, but can be marshaled across application domain boundaries, can be used with multiple waits, and can be used to synchronize threads in different processes

Semaphores: represent a named (system wide) or local semaphore, can be used to control access to a pool of resources

AutoResetEvent: provide exclusive access to a resource. When set, the event releases the waiting thread and immediately resets, blocking subsequent threads.

ManualResetEvent is useful when one thread must complete an activity before other threads can proceed.

Important Methods

  • WaitOne
  • WaitAny
  • WaitAll
  • SignalAndWait

SignalAndWait: A thread can signal an EventWaitHandle and then block on it, as an atomic operation, by calling this static method


References

Monday, May 19, 2008

Links for Week 19, 2008

Coding > .Net

Coding > SQL

Finance

Wednesday, May 14, 2008

Commodities, USA Chinese Economies, USD and Yuan - The Relation

As of May 2008, USA is seeing a slow down, China is seeing higher inflation, Commodities are at all time highs. I tried to think logically through all this to see what some of the outcomes could be.

  1. Chinese inflation at 8.5% yoy, near record highs
    1. Increased production costs, higher export prices [6]
      1. Imported consumer goods get more expensive in USA [6]
        1. Additional upward pressure on USA inflation [12]
          1. US Fed eventually increase fed rates [18]
            1. USD rises [18]
              1. Commodities cool down [18]
      2. Less US demand for imported consumer goods , especially with high gas and food prices [12]
        1. Less production in China  [18]
          1. Chinese economy slows down  [24]
          2. Less demand for commodities from China [18]
            1. Commodities cool down [18]
    2. Chinese Yuan rises [6]
      1. Exports become less profitable [6]
        1. Chinese economy slows down [12]
    3. Chinese central bank controls inflation (this week boosted bank reserve requirements by 50 basis points to a record high of 16.5%) [12]
      1. Chinese economy slows down [18]

To conclude, over the next 2 years, I expect to see the following in chronological order:

  • Higher Chinese inflation
    • USA further slows down
    • Chinese Yuan rises
      • Chinese economy slows down
        • Commodities cool down
        • USD rises

Saturday, May 10, 2008

Links for Week 18, 2008

Coding > SQL

Finance

ThreadAbortException in your C# .Net code?

I was recently asked by someone to help debug a ThreadAbortException. Here's the simplified code ...

public class MyThread
{
 public void Run()
 {
     while( true )
     {
         try
            {
             lock( LockObj )
             {
                 Monitor.Wait( LockObj );
         }   }
         catch( Exception ex )
         {
             Console.WriteLine( ex.Message );
}   }   }   }
public void ThreadRunTest()
{
 MyThread thread = new MyThread();
 ThreadStart ts = new ThreadStart( thread.Run );
 Thread t = new Thread( ts );
 t.Start();
}

Running this results in the following exception message:

A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll

As the exception suggests, it seems MyThread is being aborted during execution. Running this sample code as a test case, you can reproduce the problem. Notice ThreadRunTest starts the thread, but does not wait for its completion. So when ThreadRunTest ends, all thread are forced to abort resulting in ThreadAbortException. So this should be a simple fix ...

public void ThreadRunTest()
{
MyThread thread = new MyThread();
ThreadStart ts = new ThreadStart( thread.Run );
Thread t = new Thread( ts );
t.Start();
t.Join();
}

Here are MSDN page on ThreadAbortException Class and Thread.Join Method

UPDATE: If you are using ThreadPool.QueueUserWorkItem, consider doing the following:

class MyClass
{
 static void Main()
 {
   AutoResetEvent autoEvent = new AutoResetEvent( false );
   ThreadPool.QueueUserWorkItem( new WaitCallback( WorkMethod ), autoEvent );
   autoEvent.WaitOne(); // Wait for background thread to end
 }
  static void WorkMethod( object stateInfo )
  {
    Console.WriteLine( "executing WorkMethod" );
    ( (AutoResetEvent)stateInfo ).Set(); // Signal that this thread is finished
  }
}

Saturday, May 3, 2008

Links for Week 17, 2008

Coding > .Net

Coding > .Net > MVC

Coding > .Net > TDD & Mocks

Coding > .Net > IoC & DI

Coding > HTML

Coding > HTML > CSS

Entrepreneurship

Startup financing cycle

Finance

Finance > Commodities

Noticeable

  • Did you hear about the SQL injection attacks, funny related strip ... Exploits of a Mom