开发者

How to unit-test that the logger was called with the correct localizable, formatted string?

In the application I am testing I want to make sure that for certain inputs the logger is being called. Some of the methods have different possible logger messages (ex. "value is malformed", "value is out of range"). Thus, I want to make sure tha开发者_运维问答t the logger is being called with the correct message.

The logger strings themselved are in a RESX and may be localized in the future. Also, the wording may change. So simply comparing with a hard-coded string could result in breaking the associated tests whenever the text changes. Since they are localizable, this would mean I would have to force the unit-test to execute under a certain culture, or is there a better way?

Complicating this, the RESX strings are actually not as simple as above, but of the form "Line {0}: Value '{1}' at column {2} is malformed." This is then used as input to string.Format() to produce "Line 12: Value '12a.45' at column 45 is malformed.", for example. This is the string which the logger then actually gets. Should I hard-code this string into the unit-test?

Edit:

I'll try to explain with some more detail, with a strongly simplified method to show what I mean:

public void ConvertSomething(object value)
{
    if (/* Check if valid value */)
    {
        var convertedValue = /* Some conversion */ ;
        if (/* Check is in range */)
        {
            // Do something
        }
        else
        {
            Logger.Log(string.Format(Resources.OutOfRange, LineNumber, convertedValue));
        }
    }
    else
    {
        Logger.Log(string.Format(Resources.InvalidValue, LineNumber, value, ColumnNumber));
    }
}

How do I test that the logger gets called with the correct message? I can't simply check if any call to the logger was made. If I give it a valid, but out-of-range value, but the validity check has a bug, it will call the logger, but with the message "invalid value", when it should actually be "out of range".

I can mock the logger, so I can see that it got called and what the parameters were. But what should I assert against?


You can change the current culture of threads in code, if the culture exists on the machine. If it doesn't exist, you need to install / create it.

As for comparing the strings used in the application (that may change), I would suggest not to make that the target of the test.

Instead, perhaps have a sanity test string in each resource that is static, and test for that. If that changes with the culture then you have loaded the correct resource and can safely assume the rest of the contents are correct also.

NUnit supports changing the culture of test harnesses:

http://www.nunit.org/index.php?p=culture&r=2.4.8

Update: I see so the issue is the test cannot look into the logger? I would suggest that you can either mock a logger than knows it is being tested and contains its own assertions, or abandon testing the logger itself and test that satellite assemblies are loaded currently on a culture change. If the logger simply uses the resource file then the .NET runtime will handle the loading of the correct file or default to the base culture file.

You can then have separate tests to show that the logger logs, without worrying about what it logs as that is covered in another test.

Update 2: I think I see what you are trying to do. Would it be possible at all to have the logger accept the string format and a params object[] args in order to get access to the string before it is inserted with specific values?

Alternatively, is it possible to make the string static or is it by nature changing each test run? It is valid for the test to have values hardcoded in them if the test itself is responsible for seeding the values in the first place. Also, as for the culture, I would address those changes separately to the changes introduced by different code paths choosing different messages.

Update 3: sorry, I could not see the wood for the trees. The test itself can build the expected string from the resx file that the code uses - and just plugs in hardcoded values. This relies on the test output not differing from each run.

If the resx changes, then so long as the number of values plugged into the formatted string doesn't change, you shouldn't need to fix either the code or the test.


You create a fake logger, and monitor that it your code is calling it when needed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜