我可以在模拟中处理不区分大小写的字符串吗?
Can I handle case insensitive string in my mock?
NUnit 3.4.1,JustMock 2016.2.713.2
我正在测试class:
public class AppManager {
public string[] GetAppSets() => Registry.LocalMachine
.OpenSubKey(@"SOFTWARE\Autodesk\AutoCAD", false)
?.GetSubKeyNames();
}
此外,我有 GetAppSets
方法的测试:
[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);
}
有效。但如果 GetAppSets
方法使用“Software\Autodesk\AutoCAD”或“software\autodesk\autocad”字符串,我的测试将失败而不是 "SOFTWARE\Autodesk\AutoCAD":如果更改字符串大小写,appSets
变量将是 null
(因为该注册表项在我的计算机上不存在)。
因此,在这种情况下,要么 测试人员需要知道GetAppSets
方法实现(错误的变体),要么处理 不区分大小写 字符串之类的参数。
是否可以使用第二种变体?
原问题的答案:
您可以使用相等断言的重载版本。
Assert.AreEqual(fakeSets, appSets, true);
签名:
public static void AreEqual(
string expected,
string actual,
bool ignoreCase)
来源:https://msdn.microsoft.com/en-us/library/ms243448.aspx
更新问题的答案:
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);
}
看来@Karolis 的回答没有抓住问题的重点。
正确的解决方案是在排列中使用匹配器以case-insensitive方式匹配键:
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);
在上面 mockKey
将与 mock
相同的实例,因为第一个参数的参数匹配器。
NUnit 3.4.1,JustMock 2016.2.713.2
我正在测试class:
public class AppManager {
public string[] GetAppSets() => Registry.LocalMachine
.OpenSubKey(@"SOFTWARE\Autodesk\AutoCAD", false)
?.GetSubKeyNames();
}
此外,我有 GetAppSets
方法的测试:
[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);
}
有效。但如果 GetAppSets
方法使用“Software\Autodesk\AutoCAD”或“software\autodesk\autocad”字符串,我的测试将失败而不是 "SOFTWARE\Autodesk\AutoCAD":如果更改字符串大小写,appSets
变量将是 null
(因为该注册表项在我的计算机上不存在)。
因此,在这种情况下,要么 测试人员需要知道GetAppSets
方法实现(错误的变体),要么处理 不区分大小写 字符串之类的参数。
是否可以使用第二种变体?
原问题的答案:
您可以使用相等断言的重载版本。
Assert.AreEqual(fakeSets, appSets, true);
签名:
public static void AreEqual(
string expected,
string actual,
bool ignoreCase)
来源:https://msdn.microsoft.com/en-us/library/ms243448.aspx
更新问题的答案:
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);
}
看来@Karolis 的回答没有抓住问题的重点。
正确的解决方案是在排列中使用匹配器以case-insensitive方式匹配键:
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);
在上面 mockKey
将与 mock
相同的实例,因为第一个参数的参数匹配器。