Click here to Skip to main content
Click here to Skip to main content
Go to top

A CultureInfo switcher with Fluent syntax

, 20 Jul 2011
Rate this:
Please Sign up or sign in to vote.
For purposes of Unit Testing in globalized applications, you could sometimes need to change the CurrentCulture to test methods against different languages. Here are a few classes that provide a Fluent syntax for switching to another culture.

Introduction

A few years ago, I came across with a treacherous bug in the COM interoperability for Microsoft Excel. To make it short, it happened that under globalization settings different than the US, some instructions were throwing the evil ComException named "Old format or invalid type library". Microsoft suggested as a workaround to set the CultureInfo to "en-US" immediately before the critical line(s) of code, taking care to restore the original CultureInfo immediately after. That made things go smoothly, but soon I realized that the dirty trick could be easily hidden in a small class that would have the task to change the CultureInfo in its constructor, having first buffered the original one in a member variable, for finally restoring it in the Dispose method.

And here is the whole code for the SwitchCultureInfo class:

using System;
using System.Globalization;
using System.Threading;

namespace Utilities
{
    internal class SwitchCultureInfo: IDisposable
    {
        private readonly CultureInfo _original;

        public SwitchCultureInfo(CultureInfo newCultureInfo)
        {
            _original = Thread.CurrentThread.CurrentCulture;
            Thread.CurrentThread.CurrentCulture = newCultureInfo;
        }

        public SwitchCultureInfo(string cultureName) : 
            this(new CultureInfo(cultureName))
        {}

        public void Dispose()
        {
            Thread.CurrentThread.CurrentCulture = _original;
        }
    }
}

Background

A few days ago, while writing Unit Tests for a globalized application, I realized that the old neat small class could have been useful for testing purposes. This is the scenario: there are a few extension methods that act as shortcuts for spitting out the week day names in the user's language, such as the following one:

public static string DayName(this DayOfWeek dayOfWeek)
{
    return CultureInfo.CurrentCulture.DateTimeFormat.GetDayName(dayOfWeek);
}

Using the Code

While writing Unit Tests, it is fine to test such methods under different globalization settings, and here's how I ended writing them (using NUnit 2.5.10):

[Test]
public void DayName()
{
    using (new SwitchCultureInfo("it-IT"))
        Assert.AreEqual(DayOfWeek.Sunday.DayName(), "domenica");

    using (new SwitchCultureInfo("en-US"))
        Assert.AreEqual(DayOfWeek.Sunday.DayName(), "Sunday");

    using (new SwitchCultureInfo("pl-PL"))
        Assert.AreEqual(DayOfWeek.Tuesday.DayName(), "wtorek");
}

That initially looked fine, but I started thinking about the Fluent syntax that many frameworks are implementing (such as NUnit itself, but also NHibernate), and the using instruction started to show the signs of its age. Why not implement some Fluent extension methods that could make the Unit Test more readable and amusing? And here's how I rewrote the Test method, now much more user-friendly:

using System;
using NUnit.Framework;
using Utilities;
using Program = System.Globalization.CultureInfo;
using Tests;

namespace Tests.Utilities
{
    [TestFixture]
    public class DayOfWeekExtensionFixture
    {
        [Test]
        public void DayNameTest()
        {
            Now.WeAreTestingTheMethod(Utilities.DayOfWeekExtension.DayName);

            When.The(Program.CurrentCulture)
            .Is("Italian")
            .And().TheCountryIs("Italy",
                Assert.AreEqual, DayOfWeek.Sunday, "domenica");

            When.The(Program.CurrentCulture)
            .Is("Polish")
            .And().TheCountryIs("Poland",
                Assert.AreEqual, DayOfWeek.Tuesday, "wtorek");

            When.The(Program.CurrentCulture)
            .Is("English")
            .And().TheCountryIs("United States",
                Assert.AreEqual, DayOfWeek.Sunday, "Sunday");
        }
    }
}

Points of Interest

A reader has pointed out that it is "Nice, but not very practical". I always appreciate criticism, and I must admit that was really a good point. Moreover, in the same day I discovered that, one more time, I simply reinvented the wheel, since NUnit already has the SetCulture attribute for switching to another culture, and that is the most concise way for accomplishing that task:

[Test, SetCulture("en-US")]
public void DayNameEn()
{
    Assert.AreEqual("Sunday", DayOfWeek.Sunday.DayName());
}

[Test, SetCulture("it-IT")]
public void DayNameIt()
{
    Assert.AreEqual("domenica", DayOfWeek.Sunday.DayName());
}

[Test, SetCulture("pl-PL")]
public void DayNamePl()
{
    Assert.AreEqual("wtorek", DayOfWeek.Tuesday.DayName());
}

History

  • 2011 July, 13 - First release.
  • 2011 July, 15 - Improved the When and Now classes.
  • 2011 July, 20 - Added the NUnit example as a more concise way for checking the correct localization.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

spartacus23
Software Developer (Senior)
Italy Italy
My name is Idalgo Cantelli. I'm a software developer skilled in .Net technologies. I work with .Net since February, 2002. I also have a strong experience as a technical trainer, having taught in more than thirty classroom courses. I'm MCTS and MCPD-EAD on .Net 2.0, planning an upgrade to 3.5.

Comments and Discussions

 
GeneralMy vote of 5 PinmemberChristophe Kamieniarz21-Jul-11 4:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140905.1 | Last Updated 20 Jul 2011
Article Copyright 2011 by spartacus23
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid