模拟对象测试技术Mock(一)

因为目前项目时间比较紧(一个月的开发周期),并且,工作流的测试步骤也比较多,所以,我决定采用一种模拟对象测试技术:Mock。Mock可以为接口生成模拟对象,从而在我们写实现代码之前就检查其逻辑和交互行为是否正确。我们选用的Mock框架是Moq 3,基于lambda语法的一款非常简单的Mock框架。

下面使用示例向大家介绍Mock测试框架的好处:

 1 IEmployee.cs
 2 namespace Thoth.FeatureProject
 3 {
 4     public interface IEmployee
 5     {
 6         int Identifier { getset; }
 7         string Name { getset; }
 8         int Age { getset; }
 9     }
10 }

1 ISeat.cs
2 namespace Thoth.FeatureProject
3 {
4     public interface ISeat
5     {
6         IEmployee Get(int identifier);
7     }
8 }

 1 MainTest.cs
 2 
 3 using Moq;
 4 using NUnit.Framework;
 5 using Thoth.FeatureProject;
 6 
 7 namespace Thoth.MoqProject
 8 {
 9     [TestFixture]
10     public class MainTest
11     {
12         [Test]
13         public void EmployeeTest()
14         {
15             var employee = new Mock<IEmployee>();
16             employee.SetupGet(p => p.Identifier).Returns(1);
17             employee.SetupGet(p => p.Name).Returns("Justina Chen");
18             employee.SetupGet(p => p.Age).Returns(28);
19             Assert.AreEqual("Justina Chen", employee.Object.Name);
20 
21             var seat = new Mock<ISeat>();
22             seat.Setup(p => p.Get(1)).Returns(employee.Object);
23             var seatReturned = seat.Object.Get(1);
24             Assert.AreEqual("Justina Chen", seatReturned.Name);
25 
26             var seatI = new Mock<ISeat>();
27             seatI.Setup(p => p.Get(It.IsAny<int>())).Returns(employee.Object);
28             var seatNewReturned = seatI.Object.Get(1);
29             Assert.AreEqual("Justina Chen", seatNewReturned.Name);
30 
31             var seatII = new Mock<ISeat>();
32             seatII.Setup(p => p.Get(It.Is<int>(id => id > 0 && id < 6))).Returns(employee.Object);
33             var seatNewConditionReturned = seatII.Object.Get(1);
34             Assert.AreEqual("Justina Chen", seatNewConditionReturned.Name);
35         }
36     }
37 }
38 

上面的测试全部通过。
大家注意到了吗,我只写了两个接口,而创建Mock对象之后,我就可以以实例的方式测试对象的行为了,如果不正确,我们这时就可以对接口的设计进行修改。下面是注释:

 1 //创建一个Mock对象(泛型)
 2 var employee = new Mock<IEmployee>();
 3 
 4 //为此Mock对象的一个属性(这行是针对Identifier)值(SetupGet是为接口的Property设置值,值在Return()方法中)
 5 employee.SetupGet(p => p.Identifier).Returns(1);
 6 
 7 //取出Mock对象的值,检查是否正确
 8 Assert.AreEqual("Justina Chen", employee.Object.Name);
 9 
10 //为Mock对象的方法设置一个参数及返回对象(Setup针对的是方法),Returns是返回对象,Get(1)中值为1的参数
11 seat.Setup(p => p.Get(1)).Returns(employee.Object);
12 
13 //这两行检查我们返回结果是否正确
14 var seatReturned = seat.Object.Get(1);
15 Assert.AreEqual("Justina Chen", seatReturned.Name);
16 
17 //这行是指任何int参数都返回此对象
18 seat.Setup(p => p.Get(It.IsAny<int>())).Returns(employee.Object);
19 
20 //这里指定了一个筛选条件
21 seat.Setup(p => p.Get(It.Is<int>(id => id > 0 && id < 6))).Returns(employee.Object);

1 //那么,下面的测试结果是?
2 var seatIII = new Mock<ISeat>();
3 seatIII.Setup(p => p.Get(1)).Returns(employee.Object);
4 var seatObject = seatIII.Object.Get(0);
5 Assert.AreEqual("Justina Chen", seatObject.Name);

seatObject.Name将报出NullRefenrenceException,因为我们Setup的是1,而希望获取的对象是0,所以,检索为空 :-)

我们项目中目前运用到的Mock技术差不多就是这样了,希望能减轻大家跑流程的步骤 :-D 随着使用的深入,会继续与大家分享。
posted @ 2009-07-28 18:48  Justina Chen  阅读(...)  评论(...编辑  收藏