Tuesday, June 17, 2008

Stupid .NET Tricks #1

If you like to Unit Test as much as I do, and you're obsessive about putting your strings in Resources files, it can be kind of tricky to make use of these Resources in your Unit Tests.

I'll show you what I mean. You want to unit test the following:

public string login(user, pw)
{
if (!validUser(user, pw))
{
return "Invalid User";
}
}

OK, so we write a test:

public void TestInvalidUser()
{
MyClass m = new MyClass();
Assert.AreEqual("Invalid User", m.login("Me","X"));
}

Now I want to move the error message into the Resources class that Visual Studio generates for you when you use the String editor on the Project Properties dialog. Now we have:

public string login(user, pw)
{
if (!validUser(user, pw))
{
return Properties.Resources.INVALID_USER;
}
}

and

public void TestInvalidUser()
{
MyClass m = new MyClass();
Assert.AreEqual(Properties.Resources.ERROR_INVALID_USER, m.login("Me","X"));
}

The problem is that the Resources class that VS generates for you will have the internal access modifier and will not be accessible to your test code (unless you include the test in the same assembly, which is sub-optimal). To the rescue comes the InternalsVisibleTo attribute. Add it to your production class, specifying the Test assembly as a friend and you code will compile. I've had mixed success getting Intellisense to recognize that it can access the other assembly, however. It doesn't stop it from compiling anyway.

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("AcmeCorp.ProjectX.Tests.TestSecurity")]

Note, also, that if the production assembly is signed, then the test assembly will need to signed as well, and the public key of the friend assembly will need to be specified as part of the assembly name.

No comments: