尝试模拟在另一个方法中调用的方法。
public virtual bool hello(string name, int age)
{
string lastName = GetLastName();
}
public virtual string GetLastName()
{
return "xxx";
}
Mock<program> name= new Mock<program>();
name.Setup(x => x.GetLastName()).Returns("qqq");
我希望方法GetLastName始终返回“qqq”。
答案 0 :(得分:7)
这应该有效,假设那些是完整的方法实现
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<MyProgram> name = new Mock<MyProgram>();
name.CallBase = true;
name.Setup(x => x.GetLastName()).Returns(stringToReturn );
var results = name.Object.hello(It.IsAny<string>(), It.IsAny<int>());
string expected = string.Format("hello {0}", results);
Assert.AreEqual(expected, results);
}
}
我仍然不太关注你的评论:
参数对Mock的真正含义是什么?是?对不起,我不太懂语法。为了澄清,mock意味着当我在我的代码中放置断点时,断点应该跳过我正在嘲笑的方法。我是对的吗?
Mock<T>
允许您模拟T
- T
类型作为通用指标,也意味着几乎所有类别。在传统中,你会嘲笑interface
,而不是实际的class
,但在上面的例子中,我们是在嘲笑一个类。对于发布的样本单元测试,单元测试的目的是测试hello(string, int)
的实现。我们知道hello(string, int)
依赖于该类中名为GetLastName()
的另一种方法。 GetLastName()
的实施虽然重要,但对于单元测试hello(string, int)
的范围并不重要。出于这个原因,我们模拟调用及其返回 - 以便测试hello(string, int)
的功能,而不必担心其依赖项的实现。
我已经用实际的类名包围了上面的内容,希望能让我们更明显地模仿类MyProgram
并提供GetLastName()
的新实现(模拟)
感谢您的回答。如果我想测试调用另一个调用另一个方法的方法的方法怎么办?例如。如果方法hello调用另一个方法怎么办?
同样的原则适用于,当您构建单元测试时(假设它们是 单元 测试,而不是集成测试或其他,您总是希望专注于测试 一个 公共方法。What's the difference between unit and integration tests?
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;
}
}
如果我们进行单元测试Bar()
,我们不关心Baz(int)
或更差DoStuff(int)
的实施情况。注意 我们不关心实施 ,我们 做 关心他们返回值。从Bar()
的角度来看,唯一重要的是Baz(int)
返回一个字符串。什么字符串?与Bar()
单元测试无关。
Bar()
的示例测试:
[TestMethod]
public void Bar_ReturnsBazValueWithBarAppended
{
// Arrange
string testBazReturn = "test";
Mock<Foo> mock = new Mock<Foo>();
mock.CallBase = true;
mock
.Setup(s => s.Baz(It.IsAny<int>())
.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<int>())); // 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<Foo> mock = new Mock<Foo>();
mock.CallBase = true;
mock
.Setup(s => s.DoStuff(It.IsAny<int>())
.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<int>())); // Verifies that DoStuff was called
}
在上面,我们现在是单元测试Baz(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);
}