我不是单元测试的新手,但是我是Moq库的新手,我遇到了一个问题。我很困惑为什么我的单元测试失败了。这是我试图编写的单元测试。
[TestInitialize]
public void SetUp()
{
//...
optionsMock = new Mock<IDictionary<string, string>>();
//...
}
[TestMethod]
public void TestFunction()
{
// Arrange
//var options = new Dictionary<string, string>() { { keyValue, true.ToString() } }; // only way to get the unit test to pass right now
optionsMock.Setup(a => a.ContainsKey(It.Is<string>(b => b == keyValue))).Returns(false);
optionsMock.Setup(c => c.Add(It.Is<string>(d => d == keyValue), It.Is<string>(e => e == true.ToString()))).Verifiable();
optionsMock.Setup(f => f.ContainsKey(It.Is<string>(g => g == keyValue))).Returns(true);
optionsMock.Setup(h => h[It.Is<string>(i => i == keyValue)]).Returns(true.ToString());
// Act
int projectId = sut.Open(stringValue, booleanValue, stringValue, stringValue, IDictionary<string, string>, out errorString);
// Assert
optionsMock.Verify(a => a.ContainsKey(It.Is<string>(b => b == keyValue)), Times.Once());
optionsMock.Verify(c => c.Add(It.Is<string>(d => d == keyValue), It.Is<string>(e => e == true.ToString())), Times.Once());
optionsMock.Verify(f => f.ContainsKey(It.Is<string>(g => g == keyValue)), Times.Once());
optionsMock.Verify(h => h[It.Is<string>(i => i == keyValue)], Times.Once()); // This fails
Assert.AreNotEqual(0, id); // This fails even if I remove the line above
}
注释掉的行是我可以通过测试的唯一方法,但我觉得我也应该能够使用模拟字典。我遇到的问题是最终sut.Open(...)调用一个内部类,它有一个IDictionary作为参数。在该方法中,检查字典是否为空。每当我在没有真实字典的情况下运行单元测试时,null检查总是计算为true,并且我得到一个错误的失败。但是,如果传入真正的字典,我会通过测试。以下是内部代码的示例。
public int Open(..., IDictionary<string, string> dictionary, ...)
{
//...
if(!dictionary.ContainsKey(key))
{
dictionary.Add(key, true);
}
InternalClass.Method(dictionary);
//...
}
这是内部类方法
public void Method(IDictionary<string, string> dictionary)
{
if(dictionary != null && dictionary.ContainsKey(key))
{
string value = dictionary[key];
//... Do something
}
else
{
//... Do something else
}
}
它总是执行其他的东西,它周围存在吗?
答案 0 :(得分:0)
仔细观察以下一行:
optionsMock.Setup(a => a.ContainsKey(It.Is<string>(b => b == keyValue))).Returns(false);
这意味着ContainsKey
应该返回false
。所以条件:
if (dictionary != null && dictionary.ContainsKey(key))
永远不会满足。
我想你打算写.Returns(true);
答案 1 :(得分:-1)
好吧所以我认为这是我很满意的答案。我在网上发现了一些其他人也使用过的地方。现在是“设置和验证”部分
bool firstCall = true;
optionsMock.Setup(a => a.ContainsKey(It.Is<string>(b => b == keyValue))).Returns(() =>
{
if (firstCall)
{
firstCall = false;
return false;
}
return true;
});
然后我在下面用以下内容验证:
optionsMock.Verify(a => a.ContainsKey(It.Is<string>(b => b == fullPath)), Times.Exactly(2));
我唯一不喜欢的是测试中增加的逻辑:(但是我没有看到任何其他方法。感谢所有的帮助!