ASP.NET MVC 3 – NUnit test project template

Piotr Kwapin posted an NUnit-based test project template for MVC 2 back in July and I used it in my ASP.NET MVC 3 project. It turned out that the LogOn method tests are failing due to the Url property on the AccountController being null. So I fixed that.

I haven’t followed Piotr’s template installation instructions, since I’m using Visual Web Developer 2010 and it doesn’t have the same support for test projects as a paid-for version of Visual Studio does. If you’re in the same situation, you can simply unzip the template zip file and grab the project files out of that. There are also a few namespace placeholders that need to be fixed up. If you have a full version of Visual Studio on hand, you can follow the instructions in Piotr’s post for installing the template and skip a lot of that manual work.

Once you have the project set up, download AccountControllerTest.zip, overwrite the AccountControllerTest.cs file you got from the template with the version from the zip file, and fix up the namespace placeholders again. All tests should pass now with MVC 3.

The gist of the changes is that I provided a mock dummy implementation of HttpResponse and HttpRequest, and changed the AccountController creation method to also instantiate a UrlHelper object.

Advertisements

On Importance of Good Method Names and Paying Attention

I spent a somewhat frustrating hour at work today trying to plot a straight line on a chart using a framework that shall remain nameless. I quickly had the slope and the y-intercept worked out and all I needed were two x values to plug into the equation to calculate some points. I already had another series plotted on the same chart and just picking the minimum and maximum x values from it was sufficient for my causes.

Naturally, I could do the legwork of figuring the min and max myself, but why do the work when the framework can do it for you? I poked around and found a couple useful methods: FindMinValue() and FindMaxValue(). I had assumed (based on Intellisense and lack of code docs) that they would return the values I needed. Then a couple things taught me that wasn’t so at all:
1. I used var to declare my variables, so I didn’t notice that the functions in question are returning integers.
2. I was wrong in my original assumption. Those methods aren’t finding and returning the min and max values. Instead, they’re returning indices into the array of points in the series, pointing me to the location of the min and max values.

I guess technically the method names didn’t lie: they are “finding” the location of the values for me. I still found that to be counterintuitive. In my opinion, FindMinValueIndex() would’ve been better.

So, the lesson is: pay attention, don’t assume anything, and if you ever release an API framework, try to be as clear as possible about the intent of your methods when you name them.

ComboBox SelectedItem vs SelectedValue Question

Annoying discovery of the day:

The following code works as you’d expect — MyProperty on the model is updated when the user picks a new item in the dropdown.

comboBox1.DataBindings.Add("SelectedValue", myModel, "MyProperty", true, DataSourceUpdateMode.OnPropertyChanged);

The following, however, doesn’t work the same way and the model update isn’t triggered until the input focus moves to another control on the form:

comboBox1.DataBindings.Add("SelectedItem", myModel, "MyProperty", true, DataSourceUpdateMode.OnPropertyChanged);

Does anybody know why? I’d investigate myself, but I don’t even know where to start. Pointers in the right direction to start the investigation or an outright explanation are both welcome.

Update: Some explanations are up on StackOverflow. In the end, I ended up binding to both SelectedValue and SelectedItem, which ensures instant model updates based on UI changes (through the SelectedValue binding), and UI updates based on programmatic model changes (through the SelectedItem binding).

Another thing to note is that when binding to SelectedValue without setting the DisplayMember/ValueMember properties, it helps to pass in “true” for the formattingEnabled binding parameter.

Replace Paper with Unit Tests: Code Snippets Edition

In my previous post about making mental notes about condition tests or new features through unit tests I offered an example of making a live template in ReSharper to automate some of the process.

This post is about achieving a similar thing in plain Visual Studio with the help of the Code Snippets feature.

Introduction to Code Snippets

In a nutshell, a code snippet in Visual Studio is either a template or a static chunk of code that is stored in a specific location and is available through IntelliSense. Visual Studio comes with some snippets pre-configured, such as “ctor“, which creates a default constructor for a class.

To use a snippet, start typing out its shortcut – either type the whole thing or wait for IntelliSense to pop up and complete it for you – and then press TAB key twice to expand the snippet into code.

There’s a detailed guide to using and creating snippets available on MSDN. For the rest of this post, I will just show what I did for my purposes.

Snippet Location and Creating New Snippets

Snippets are located in a specific folder under your installation of Visual Studio, so you’ll have a snippet collection per VS version. On my machine, where I used default installation paths, C# snippets for VS 2008 and 2010 are in the following folders:

C:\Program Files\Microsoft Visual Studio 9.0\VC#\Snippets\1033\Visual C#

C:\Program Files\Microsoft Visual Studio 10.0\VC#\Snippets\1033\Visual C#

You can use the Code Snippet Manager (available through Tools->Code Snippets Manager… menu item) to explore currently installed snippets for various languages.

To create a new snippet, you can simply write its XML definition (see below for my example or read the MSDN guide for more info), save the file with the .snippet extension and drop it in the appropriate folder. Visual Studio will see it without needing to restart.

You can also use a visual editor such as the open source Snippet Editor, which now includes support for Visual Studio 2010.

Unimplemented Unit Test Snippet

Here’s my code snippet in its entirety:

<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Unimplemented Unit Test</Title>
<Shortcut>test</Shortcut>
<Description>Code snippet for a failing test placeholder</Description>
<Author>Anna Lear (http://annalear.ca)</Author>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>testName</ID>
<ToolTip>Descriptive test name</ToolTip>
<Default>NewTest</Default>
</Literal>
<Literal>
<ID>testBody</ID>
<ToolTip>Test contents</ToolTip>
<Default>Assert.Fail("Implement me!");</Default>
</Literal>
</Declarations>
<Code Language="CSharp">
<![CDATA[
[Test]
public void $testName$()
{
$testBody$
}
]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>

I wrote it within Visual Studio 2010 and it helpfully provided IntelliSense support and guidance, which made writing the XML really easy.

Now when I type in “test” in a class and press TAB twice, the code within the CDATA portion of the snippet gets pasted into my code. “NewTest” and “Assert.Fail(“Implement me!”);” lines will be highlighted and I can navigate between then with TAB and Shift-TAB if I need to edit them. I typically always edit the name of the test, and only edit the body when I intend to implement the test at the same time.

Couple things to keep in mind:

1. When you add literals to a snippet, their IDs are case-sensitive.

2. If you want to preserve your formatting (multiple lines, etc.), make sure that you’re code is within a single CDATA element. Otherwise you’ll end up with all your code on the same line, which probably isn’t what you want.

Download

You can either copy the snippet above and do the legwork of placing it in a file and the correct location, or download the .snippet file or the .vsi installer, the latter of which will allow you to easily install the above snippet into any version of Visual Studio (2005 or newer) that you have on your machine.

Replace paper with unit tests

TDD, or Something Like It

When I write new code, I often start out following the TDD principles: write a test, make it pass, refactor. But often, as I’m doing the refactoring or even the initial implementation, I find myself thinking of other tests I should do or features I should add. Instead of jotting things down on a piece of paper, I’ve started creating method stubs for my future tests that effectively document my development path for me:

[Test]
public void CreateItemThrowsExceptionWhenNameIsDuplicate()
{
}

This is nice and I can go in and fill in the details of those tests as I work through my code. However, it’s still easy to forget or miss a test, since these will automatically show up as passing. So we can add an Assert.Fail() call:

[Test]
public void CreateItemThrowsExceptionWhenNameIsDuplicate()
{
    Assert.Fail("Implement me!");
}

This will now remind you to implement tests as you run them locally. Great!

Why bother?

The benefits are pretty clear:

  1. Even if you’re the type of developer to write tests after you write the actual code, this will help you make sure you’re not forgetting anything. It can save you from either trying to find that piece of paper where you wrote down your thoughts three days ago or from staring at your just-written code to identify parts that need testing.
  2. This promotes clear and meaningful test method names, since you have to be able to remember what you were going to test when you wrote the stub.
  3. As you fill in your tests, you will use your own code. If you’re writing an API or just a new set of public methods, you will see pretty quickly if they’re easy to use or if the consumers of your methods will come after you with torches and pitchforks.

My, that’s a lot of code to type in every time…

Typing all that out every time can, indeed, be quite tedious. That’s where Live Templates from ReSharper come in to save the day. I have a template set up that when I start typing in the word “test”, Intellisense picks it up and expands it to create a skeleton method that looks like the ones above, prompting me to fill in the method name and contents (with the Assert.Fail() call filled in by default).

Creating a Live Template with ReSharper

  1. Go to ReSharper->Live Templates… in Visual Studio to bring up the Templates Explorer dialog.
  2. Go under “User Templates” in the Live Templates tab and click the “New Template” button.
  3. In the window that comes up, pick your shortcut (mine is just “test”) and paste the following in the template’s code window:
    [Test]
    public void $TESTNAME$()
    {
         $ACTION$
    }

$TESTNAME$ and $ACTION$ are variables that can be pre-defined (as I will explain below) or be left undefined to let you type them in as needed. I leave $TESTNAME$ undefined and set $ACTION$ as follows:

  1. Click on “choose macro” in the Value column on the right.
  2. Select “Constant Value” and click OK.
  3. Paste “Assert.Fail(“Implement me!”);” in the dialog box that comes up and click OK again.

That’s it! Save your template and it becomes available to you in all your projects. Whenever you need a new test, just start typing “test” (or whatever shortcut you picked) and press TAB to expand it when Intellisense figures out what you’re doing.

The final result should look something like this:

Live Template Example

Live Template Example

For more information on ReSharper templates see their site.

No ReSharper?

I have tried to produce something similar with just plain recorded macros, but I’m doing something wrong there and my attempts haven’t worked at all. I’ll post again about it if/when I figure that part out.

ILMerge + Castle + Log4Net

At work we have recently merged the various Castle assemblies into one with ILMerge. It has worked great, but we found one gotcha with the Log4Net facility. Castle’s LoggingFacility class defines class types of various logging factories as static strings, which aren’t picked up by ILMerge.

The solution has two parts:
1. Use the CustomLoggerFactory config parameter:

<facility id="LoggingFacility" loggingApi="Custom" customLoggerFactory="Castle.Services.Logging.Log4netIntegration.Log4netFactory, <Your Merged Assembly>" type="Castle.Facilities.Logging.LoggingFacility, <Your Merged Assembly>" />

2. Place your actual logging configuration into a file called “log4net.config” and place that file in the same folder as the file that contains the above facility definition.

Sources: Castle-Project-Users mailing list and Castle Monorail docs.

Extension methods in .NET 2.0

Due to the nature of our client base, we still target .NET 2.0 at work. The side-effect being, of course, the inability to use the latest and greatest and sexiest of what C# has to offer these days.

I was setting out to write some static helper methods this morning, and on a lark decided to Google for extension method support. Sometimes the compiler is nice enough to take 3.0 features (such as the var keyword) and translate them into code that’s palatable for .NET 2.0.

Truly, ask and ye shall receive! Success! While in newer versions of the framework, you’d import System.Core.dll to add extension support, all that’s really needed is the definition of the ExtensionAttribute class. This can be added anywhere in your code that targets .NET 2.0:

namespace System.Runtime.CompilerServices
{
    public sealed class ExtensionAttribute : Attribute { }
}

Extensions work like a charm after that.

XamlParseException during application startup

If a WPF application encounters any problems during the creation of the main window, you will be presented with a rather useless System.Windows.Markup.XamlParseException:

“Cannot create instance of ‘Window1’ defined in assembly ‘YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. Exception has been thrown by the target of an invocation. Error in markup file ‘Window1.xaml’ Line 1 Position 9.”

The inner exception is similarly not giving much information:

{“Exception has been thrown by the target of an invocation.”}

The trick to getting to the root of the problem is simple. There are a couple ways to do so:

  1. Wrap the code in the constructor of the Window in a try/catch block. This will provide you with access to the actual exception and its stack trace.
    public MainWindow()
    {
        try
        {
            InitializeComponent();
    
            // other code, if any
        }
        catch(Exception ex)
        {
            // log the exception -- this is the real culprit
        }
    }
  2. Open the Exceptions window in Visual Studio (Debug -> Exceptions…) and check the “Common Language Runtime Exceptions” checkbox in the Thrown column. Re-run your application with the debugger attached, and the application will break on the exception that’s getting wrapped in XamlParseException.

Test your serialization!

Something I learned today: when making use of user profile support in ASP.NET 2.0, make sure to get the XML serialization of your objects right. Otherwise System.Web.Profile.ProfileBase will happily swallow any and all exceptions while loading your profile objects and you will spend 6 hours tearing your hair out.

*sigh*

Sorting a C# dictionary by value

This is fairly simple: create a list to hold your dictionary’s objects and use a delegate to provide a custom sorting mechanism.

Dictionary<int, double> myDictionary = new Dictionary<int, double>();

public Dictionary<int, double> SortMyDictionaryByValue()
{
    List<KeyValuePair<int, double>> tempList = new List<KeyValuePair<int, double>>(myDictionary);

    tempList.Sort(delegate(KeyValuePair<int, double> firstPair, KeyValuePair<int, double> secondPair)
                    {
                        return firstPair.Value.CompareTo(secondPair.Value);
                    }
                 );

    Dictionary<int, double> mySortedDictionary = new Dictionary<int, double>();
    foreach(KeyValuePair<int, double> pair in tempList)
    {
        mySortedDictionary.Add(pair.Key, pair.Value);
    }

    return mySortedDictionary;
}