Andrey Bushman
Andrey Bushman

Reputation: 12486

Can I handle case insensitive string in my mock?

NUnit 3.4.1, JustMock 2016.2.713.2

I have the class under test:

public class AppManager {
    public string[] GetAppSets() => Registry.LocalMachine
        .OpenSubKey(@"SOFTWARE\Autodesk\AutoCAD", false)
        ?.GetSubKeyNames();
}

Also, I have the test for GetAppSets method:

[Test]
public void GetAppSets_Returns_ValidValue() {

    const string subkey = @"SOFTWARE\Autodesk\AutoCAD";
    /* The sets of applications which are based on 
     * AutoCAD 2009-2017. */
    string[] fakeSets = new[] { "R17.2", "R18.0",
        "R18.1", "R18.2", "R19.0", "R19.1", "R20.0",
        "R20.1","R21.0" };

    RegistryKey rk = Mock.Create<RegistryKey>();

    Mock.Arrange(() => rk.GetSubKeyNames()).Returns(
        fakeSets);

    Mock.Arrange(() => Registry.LocalMachine.OpenSubKey
    (subkey, false)).Returns(rk);

    AppManager appMng = new AppManager();
    string[] appSets = appMng.GetAppSets();

    Assert.AreEqual(fakeSets, appSets);
}

It works. But my test will be failure if GetAppSets method uses "Software\Autodesk\AutoCAD" or "software\autodesk\autocad" string instead of "SOFTWARE\Autodesk\AutoCAD": the appSets variable will be null if string case will be changed (because that registry key doesn't exist on my computer).

So, at this case either tester needs to know theGetAppSets method implementation (the bad variant), or to handle parameter like the case insensitive string.

Is it possible to use the second variant?

Upvotes: 2

Views: 1147

Answers (2)

Stefan Dragnev
Stefan Dragnev

Reputation: 14473

It seems that the answer by @Karolis misses the point of the question.

The correct solution is to use a matcher in the arrangement to match the key in a case-insensitive manner:

    var mock = Mock.Create<RegistryKey>();
    Mock.Arrange(() => Registry.LocalMachine.OpenSubKey(
        Arg.Matches<string>(s => StringComparer.OrdinalIgnoreCase.Equals(s, @"SOFTWARE\Autodesk\AutoCAD")),
        Arg.AnyBool)
    ).Returns(mock);


    var mockKey = Registry.LocalMachine.OpenSubKey(@"software\autodesk\autocad", false);

In the above mockKey will be the same instance as mock, because of the argument matcher on the first argument.

Upvotes: 0

Karolis Kajenas
Karolis Kajenas

Reputation: 1543

Answer to original question:

You can use an overloaded version of equality assertion.

Assert.AreEqual(fakeSets, appSets, true);

Signature:

public static void AreEqual(
string expected,
string actual,
bool ignoreCase)

Source: https://msdn.microsoft.com/en-us/library/ms243448.aspx

Answer to updated question:

for(int i = 0; i < appSets.Length, i++)
{   // If there is mismatch in length Exception will fail the test.
    Assert.AreEqual(fakeSets[i], appSets[i], true);
}

Upvotes: 1

Related Questions