Thursday, August 30, 2007

I was messing around with some unit tests this week and I came across an unexpected benefit while working on code that worked with a COM object. When you add a reference to a COM library in .NET, you'll get an interface as well an implementation of that interface that forwards the calls to the COM objects.

Because an interface is created for the COM objects as well as the implementation, you can mock the COM dependency with Rhino Mocks or some other mocking framework. Just code against the interface instead of the concrete implementation and inject the concrete implementation via dependency injection for the normal scenario.

Let's say you wanted to unit test some code that had a dependency on the Windows Media Player COM object. Here's how you could do it.*

image

// Code to be tested
public class SomeClass
{
   private WMPLib.WindowsMediaPlayer _player;

   public SomeCode(WMPLib.WindowsMediaPlayer player)
   {
      _player = player;
   }

   public void DoSomething()
   {
      _player.enabled = false;
   }
}

// Unit test
[TestFixture()]
public class SomeCodeTest
{
   [Test()]
   public void PlayerEnabledShouldBeSetCorrectly()
   {
      MockRepository mocks = new MockRepository();

      // Mock the WMP interface... note that even 
// though it doesn't start with an 'I', // it is still an interface... WMPLib.WindowsMediaPlayer player = mocks.CreateMock(); // Inject the mocked WMP object SomeClass sc = new SomeClass(player); using (mocks.Record()) {
// Expect player.enabled to be set to false player.enabled = false; } using (mocks.Playback()) { sc.DoSomething(); } } }

I tried this code out and the test runs fine. Note the comment where the mock object is actually being created. For some reason, the interface to the COM object isn't named with an 'I'. It still is an interface, though. And you can create the COM object by saying 'new WMPLib.WindowsMediaPlayer' though I think that is some COM interop magic going on there (I'm guessing the CoClass attribute on the interface has something to do with this magic).

* I'm not actually mocking Windows Media Player in any of my code and I have no idea how well it will work. I do know that I can mock some of our own COM objects without any problems, though.

posted on Thursday, August 30, 2007 3:36:44 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Tuesday, August 21, 2007

I found myself writing the following code this evening:

public T GetItem<T>(string name)
{
    string result = node.SelectSingleNode(name).InnerText.Trim();
 
    return (T)GetConverter(typeof(T)).ConvertFromString(result);
}
 
private TypeConverter GetConverter(Type objectType)
{
    if (objectType.Equals(typeof(int)))
        return new Int32Converter();
    else if (objectType.Equals(typeof(bool)))
        return new BooleanConverter();
    else if (objectType.Equals(typeof(string)))
        return new StringConverter();
    else
        throw new ArgumentException("Does not support casting to " + objectType.Name);
}

Don't ever write code like this. Read the documentation which explicitly says that "you should never create an instance of a BooleanConverter". If you follow their advice, your code will become much cleaner. Like so:

public T GetItem<T>(string name)
{
    string result = node.SelectSingleNode(name).InnerText.Trim();
    return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(result);
}
posted on Tuesday, August 21, 2007 8:39:58 PM (Central Standard Time, UTC-06:00)  #    Comments [0]

I was looking through programming.reddit.com today and discovered that IronLisp now has a website on Codeplex. I haven't coded in LISP since college, but it was certainly an interesting experience.

This got me thinking - how many Iron* projects are there now? This is what I've come up with:

1) IronPython - the original Iron project?

2) IronRuby

3) IronLisp

4) IronXSLT - (thanks Michael!)

5) ...

Hmmm... as I was thinking about this blog post, I seemed to think there were a lot more out there. I know there are a lot of other languages that support the CLR, but I guess the Iron designation seems to be fitting with the languages that are build on top of the DLR. I'm a little curious if the Smalltalk/DLR implementation (Vista Smalltalk) will make the name change to IronSmalltalk or not.

So where did the Iron naming scheme come from anyway? Why not Nython1 or NRuby2? :-)

1 - The Java implementation is Jython.

2 - The Java implementation is JRuby.

posted on Tuesday, August 21, 2007 6:47:02 PM (Central Standard Time, UTC-06:00)  #    Comments [3]
 Friday, August 10, 2007

For your enjoyment, here is some great dialogue from the movie Airplane. Why am I providing this? Because it is funny and because I wanted to.

Roger Murdock: We have clearance, Clarence.
Capt. Clarence Oveur: Roger, Roger. What's our vector, Victor?
Tower: Tower Radio, clearance, over.
Oveur: That's 'Clarence Oveur', over.
Tower: Roger.
Roger Murdock: Huh?
Tower: Roger, over.
Roger Murdock: What?
Capt. Oveur: Huh?

Many thanks to Kaelin for providing this.

posted on Friday, August 10, 2007 7:15:34 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Tuesday, August 07, 2007

I work with the WebBrowser control that was introduced in .NET 2.0 (as well as the ActiveX browser it is based on) a lot at work. As a result, I've come to learn a lot about some of the various intricacies that Internet Explorer has as well as the browser control in general.

Because we're not running some of our web pages in Internet Explorer but in a custom web browser, unit testing frameworks like Watir and Watin won't work for us. They make use of the Internet Explorer COM application. Unless we want to fork one of those frameworks as well as provide an automation interface into our custom browser, I don't see either of those frameworks working for us.

However, Selenium will work fine!

Selenium runs in the browser!

image

That's a picture of a little WinForms application I put together that is hosting the WebBrowser control. As you can see, all but one of shipped Selenium tests passed (the only one that failed had to do with opening an XHTML page).

Looks pretty good to me!

posted on Tuesday, August 07, 2007 12:51:25 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
 Thursday, August 02, 2007

(note - if you're reading this in a feed reader like Google Reader, sorry - the code snippets look awful... if anyone has any suggestions on good ways to get code to look good in the webpage and feed readers, I'd appreciate it)

Given this:

    delegate void WorkDelegate();
    interface ISomeInterface
    {
        void Execute();
    }

 

What is the difference between this class

    class TestCaseOne
    {
        ISomeInterface something = Activator.GetObject(typeof(ISomeInterface), "http://some.url.com/") as ISomeInterface;

        public TestCaseOne()
        {
            BackgroundWorker wkr = new BackgroundWorker();
            wkr.DoWork += new DoWorkEventHandler(wkr_DoWork);
            wkr.RunWorkerAsync();
        }

        void wkr_DoWork(object sender, DoWorkEventArgs e)
        {
            something.Execute();
        }
    }

and this class?

    class TestCaseTwo
    {
        ISomeInterface something = Activator.GetObject(typeof(ISomeInterface), "http://some.url.com/") as ISomeInterface;

        public TestCaseTwo()
        {
            WorkDelegate dlg = new WorkDelegate(something.Execute);
            dlg.BeginInvoke(MyCallback, new object[] { dlg });
        }

        private void MyCallback(IAsyncResult iar)
        {
            object[] asyncState = iar.AsyncState as object[];
            WorkDelegate dlg = asyncState[0] as WorkDelegate;

            dlg.EndInvoke(iar);
        }
    }

 

Both classes have a field named something that is a reference to an HTTP remoting proxy that has been published at http://some.url.com. Let's assume that the the HTTP Remoting configuration has already been set up. Both call the Execute method defined on the interface, but one is using a BackgroundWorker for threading and the other is using the BeginInvoke/EndInvoke means of threading. Big deal, right?

There isn't a huge difference just looking at the code -- except that with TestCaseOne, the remoting call will result in a blocked thread whereas TestCaseTwo will not. In TestCaseOne, the background thread will block on the something.Execute() call and wait for it to return. In TestCaseTwo, the WorkDelegate BeginInvokes on the transparent remoting proxy. There isn't any code to block on. Instead, the framework will let you know when your remoting call returns.

Why does this matter? When you have a blocked thread, you basically have wasted CPU cycles where it is blocking instead of working. This likely won't matter much if you're not working with a lot of threads, but it can cause performance problems if you're working with a lot of threads.

On the other hand, when TestCaseTwo calls back to let you know the remoting call has completed, it will not call back on the calling thread. BackgroundWorker is smart enough to invoke back to the UI thread if needed. Both have their pluses and minuses. The BackgroundWorker component does make the code a little more easy to read and it handles invoking back to the UI thread. However, if you're working with a lot of threads, you might try using the delegate approach instead, so as to avoid any blocked threads.

posted on Thursday, August 02, 2007 9:40:25 AM (Central Standard Time, UTC-06:00)  #    Comments [0]