模拟一种测试方法

试图模拟在另一个方法中调用的方法。

public virtual bool hello(string name, int age) { string lastName = GetLastName(); } public virtual string GetLastName() { return "xxx"; } Mock name= new Mock(); name.Setup(x => x.GetLastName()).Returns("qqq"); 

我希望方法GetLastName始终返回“qqq”。

这应该有效,假设这些是完整的方法实现

 public class MyProgram { public bool hello(string name, int age) { string lastName = GetLastName(); return string.Format("hello {0}", lastName); } public virtual string GetLastName() { return "xxx"; } } public class MyProgramTests { [TestMethod] public void MyTest() { string stringToReturn = "qqq"; Mock name = new Mock(); name.CallBase = true; name.Setup(x => x.GetLastName()).Returns(stringToReturn ); var results = name.Object.hello(It.IsAny(), It.IsAny()); string expected = string.Format("hello {0}", results); Assert.AreEqual(expected, results); } } 

我还没有完全听完你的评论:

参数对Mock的真正含义是什么? 是? 对不起,我不太懂语法。 为了澄清,mock意味着当我在我的代码中放置断点时,断点应该跳过我正在嘲笑的方法。 我对吗?

Mock允许你模拟一种类型的TT作为通用指标,也意味着几乎任何一个类。 在传统中,你会嘲笑一个interface ,而不是一个真正的class ,但在上面的例子中,我们正在嘲笑一个类。 对于发布的样本unit testing,unit testing的目的是测试hello(string, int) 。 我们知道hello(string, int)依赖于该类中另一个名为GetLastName()GetLastName()的实现虽然重要,但对于unit testinghello(string, int)的范围并不重要。 出于这个原因,我们模拟调用及其返回 – 以便测试hello(string, int)的function,而不必担心其依赖项的实现。

我用实际的类名包围了上面的内容,希望能让我们更明显地模拟MyProgram类并提供GetLastName()的新实现(模拟GetLastName()

谢谢你的回答。 如果我想测试调用另一个调用另一个方法的方法的方法怎么办? 例如。 如果方法hello调用另一个方法怎么办?

同样的原则也适用,当你构建unit testing时(假设它们是单元测试,而不是集成测试或其他,你总是想集中精力测试一种公共方法。 unit testing和集成测试有什么区别?

 public class Foo { public string Bar() { return string.Format("{0}Bar", Baz(5));; } public virtual string Baz(int someNumber) { return string.Format("{0}Baz", DoStuff(someNumber).ToString()); } public virtual int DoStuff(int someNumber) { return someNumber+1; } } 

如果我们是unit testingBar()我们不关心Baz(int)的实现,甚至更糟糕的是DoStuff(int) 。 注意我们不关心实现 ,我们关心它们返回值。 从Bar()的角度来看,唯一重要的是Baz(int)返回一个字符串。 什么字符串? Bar()的unit testing无关紧要。

Bar()示例测试:

 [TestMethod] public void Bar_ReturnsBazValueWithBarAppended { // Arrange string testBazReturn = "test"; Mock mock = new Mock(); mock.CallBase = true; mock .Setup(s => s.Baz(It.IsAny()) .Returns(testBazReturn); // Act var results = mock.Object.Bar(); // Assert Assert.AreEqual(string.Format("{0}{1}", testBazReturn, "Bar"), results); mock.Verify(v => v.Baz(It.IsAny())); // Verifies that Baz was called } 

请注意,在上面,我们对Baz(int)DoStuff(int)的实际实现并不重要,因为我们忽略了Baz(int)的实际实现,而DoStuff(int)甚至没有发挥作用。

现在,如果我们要测试Baz(int)我们只需遵循相同的心态:

 [TestMethod] public void Baz_ReturnsDoStuffValueWithBazAppended { // Arrange int testDoStuffReturn = 1; Mock mock = new Mock(); mock.CallBase = true; mock .Setup(s => s.DoStuff(It.IsAny()) .Returns(testDoStuffReturn); // Act var results = mock.Object.Baz(5); // Assert Assert.AreEqual(string.Format("{0}{1}", results, "Baz"), results); // Validates the result mock.Verify(v => v.DoStuff(It.IsAny())); // Verifies that DoStuff was called } 

在上面,既然我们是unit testingBaz(int) ,我们不关心Bar() ,我们在DoStuff(int)唯一关心的是它返回一个值(但不是它如何到达在那个价值。)

最后是DoStuff(int)

 [TestMethod] public void DoStuff_ReturnsParameterPlusOne() { // Arrange Foo foo = new Foo(); int passed = 1; int expected = passed + 1; // Act var results = foo.DoStuff(passed); // Assert Assert.AreEqual(expected, results); }