今天我在代码中更改为使用StringDictionary
而不是Dictionary<string,string>
,但旧的单元测试失败了。所以我写了一个小单元测试来测试它。
这是我的小测试:
using Rhino.Mocks;
using NUnit.Framework;
//using CustomDictionary = System.Collections.Specialized.StringDictionary;
using CustomDictionary = System.Collections.Generic.Dictionary<string, string>;
namespace ConsoleApplication1
{
public interface ITest
{
void DoSth(CustomDictionary dic);
}
public class OneTest : ITest
{
public void DoSth(CustomDictionary dic) {/*do nothing*/}
}
[TestFixture]
public class TestClass
{
[Test]
public void Test1()
{
var mockRepository = new MockRepository();
var test = mockRepository.StrictMock<ITest>();
using (mockRepository.Record())
{
Expect.Call(() => test.DoSth(new CustomDictionary { { "Test", "Test1" } }));
}
test.DoSth(new CustomDictionary { { "Test", "Test1" } });
mockRepository.VerifyAll();
}
}
}
如果我使用Dictionary<string,string>
,测试将通过,但是当我使用StringDictionary
时,测试失败。
这里有什么问题?
答案 0 :(得分:1)
问题来自StringDictionary
实例比较。没有重写的Equals
方法,因此实例不是通过内容进行比较,而是通过引用进行比较。如果您将使用相同的实例,则测试将通过:
[Test]
public void Test1()
{
var mockRepository = new MockRepository();
var test = mockRepository.StrictMock<ITest>();
var dictionary = new CustomDictionary { { "Test", "Test1" } };
using (mockRepository.Record())
Expect.Call(() => test.DoSth(dictionary));
test.DoSth(dictionary);
mockRepository.VerifyAll();
}
您可以覆盖Equals
课程上的CustomDictionary
以进行原始测试通过:
public override bool Equals(object obj)
{
CustomDictionary other = obj as CustomDictionary;
if (other == null)
return false;
if (Count != other.Count)
return false;
foreach (string key in Keys)
{
if (!other.ContainsKey(key))
return false;
if (this[key] != other[key])
return false;
}
foreach (string key in other.Keys)
{
if (!ContainsKey(key))
return false;
}
return true;
}
BTW我希望这不是你真正的考验,因为你在这里测试模拟,而不是测试你的代码。
为什么您的代码与字典一起使用:
据我了解RhinoMocks实现,Rhino.Mocks.Impl.Validate
类用于参数验证。您可以查看它的ArgsEqual
方法实现:
public static bool ArgsEqual(object[] expectedArgs, object[] actualArgs)
{
return RecursiveCollectionEqual(expectedArgs, actualArgs);
}
我留给你RecursiveCollectionEqual
的详细信息,但有趣的部分是参数比较:
if (current == null)
{
if (actual != null)
return false;
}
else if (!SafeEquals(current, actual))
{
if (current is ICollection)
{
if (!RecursiveCollectionEqual((ICollection)current, (ICollection)actual))
return false;
continue;
}
return false;
}
如您所见,如果参数为ICollection
,那么Rhino会更深入地比较预期和实际的集合。 Dictionary
实施ICollection
,但StringDictionary
不实现StringDictionary
。因此,Equals
类型的参数仅通过引用进行比较。
更新:没有注意到,你有一个别名。只需从类型继承,您就可以覆盖public class CustomDictionary : StringDictionary
:
{{1}}
答案 1 :(得分:0)
我不知道这是否有帮助,但两者之间的主要区别在于StringDictionairy会自动小写所有键(测试成为测试)。也许这就是测试失败的原因?
答案 2 :(得分:0)
当检查Expect.Call()中传递的参数是否与实际传递的参数匹配时,Rhino Mocks比较按引用。 您的代码中的问题是您创建2个不同对象的自定义词典,一个用于期望,一个用于实际调用,因此它们不匹配:
using (mockRepository.Record())
{
Expect.Call(() => test.DoSth(new CustomDictionary { { "Test", "Test1" } }));
}
test.DoSth(new CustomDictionary { { "Test", "Test1" } });
它可以很容易地修复如下(也删除重复):
var myDictionary = new CustomDictionary { { "Test", "Test1" } }));
using (mockRepository.Record())
{
Expect.Call(() => test.DoSth(myDictionary);
}
test.DoSth(myDictionary );