遗留代码的测试
在大多时候代码的测试很难,因为很多代码无法进行参数注入,那么这个时候有一款不受限的隔离框架TypeMock供你使用,不过遗憾这款软件是付费的一个隔离框架,有15天的免费使用权,如果能解决你现有的问题我想这份费用并不能算多。TypeMock的官方下载http://www.typemock.com/。下面开始看看TypeMock是怎么样使用的。
1:伪造一个静态的方法来看一个例子
被测试的静态方法
public static int DoSomethingSpecialOnALeapYear() { if ((DateTime.Now.Month == 3) && (DateTime.Now.Day == 29)) return 100; return 0; }
public static int DoSomethingSpecialOnALeapYear() { if ((DateTime.Now.Month == 3) && (DateTime.Now.Day == 29)) return 100; return 0; }
测试方法
1 [TestMethod, Isolated] 2 public void FakingDateTime() 3 { 4 Isolate.WhenCalled(() => DateTime.Now).WillReturn(new DateTime(2016, 3, 29));//当调用当前时间的时候会返回指定的时间 5 int result = MyStatic.DoSomethingSpecialOnALeapYear(); 6 Assert.AreEqual(100, result); 7 }
1 [TestMethod, Isolated] 2 public void FakingDateTime() 3 { 4 Isolate.WhenCalled(() => DateTime.Now).WillReturn(new DateTime(2016, 3, 29));//当调用当前时间的时候会返回指定的时间 5 int result = MyStatic.DoSomethingSpecialOnALeapYear(); 6 Assert.AreEqual(100, result); 7 }
2:伪造一个sealed的类
被测试的静态方法
1 public static bool SignedIn { get; set; } 2 3 public static bool SignOut(HttpContext current) 4 { 5 if (SignedIn) 6 { 7 HttpSessionState session = current.Session; 8 session.Abandon(); 9 return true; 10 } 11 return false; 12 }
1 public static bool SignedIn { get; set; } 2 3 public static bool SignOut(HttpContext current) 4 { 5 if (SignedIn) 6 { 7 HttpSessionState session = current.Session; 8 session.Abandon(); 9 return true; 10 } 11 return false; 12 }
如果我们要保证上面的方法能不在依赖HttpContext 那么我们必须要注入这个依赖我们看测试代码
1 [TestMethod, Isolated] 2 public void FakingHttpContext() 3 { 4 var fakeHttp = Isolate.Fake.Instance<HttpContext>();//需要注入的伪对象 5 MyStatic.SignedIn = true; 6 var result = MyStatic.SignOut(fakeHttp); 7 Assert.AreEqual(true, result); 8 }
1 [TestMethod, Isolated] 2 public void FakingHttpContext() 3 { 4 var fakeHttp = Isolate.Fake.Instance<HttpContext>();//需要注入的伪对象 5 MyStatic.SignedIn = true; 6 var result = MyStatic.SignOut(fakeHttp); 7 Assert.AreEqual(true, result); 8 }
3:重写伪造类中的方法
如果一些类现在要按照我们的需要来返回相应的值我们来看看下面这个例子
1 public static bool IsMySiteNameTypemock(Process process) 2 { 3 var name = process.MachineName; 4 if (process.MainModule.Site.Name.StartsWith("Typemock")) 5 return true; 6 else 7 return false; 8 }
1 public static bool IsMySiteNameTypemock(Process process) 2 { 3 var name = process.MachineName; 4 if (process.MainModule.Site.Name.StartsWith("Typemock")) 5 return true; 6 else 7 return false; 8 }
为了上面的程序正常工作那么我们必须需要通过site.Name以Typemock开始所以在测试中我们必须这么做
1 [TestMethod, Isolated] 2 public void SetBehaviorOnChainExample() 3 { 4 var fake = Isolate.Fake.Instance<Process>(); 5 Isolate.WhenCalled(() => fake.MainModule.Site.Name).WillReturn("Typemock rocks");//设置Site.Name 6 var result = MyStatic.IsMySiteNameTypemock(fake); 7 Assert.AreEqual(true, result); 8 }
1 [TestMethod, Isolated] 2 public void SetBehaviorOnChainExample() 3 { 4 var fake = Isolate.Fake.Instance<Process>(); 5 Isolate.WhenCalled(() => fake.MainModule.Site.Name).WillReturn("Typemock rocks");//设置Site.Name 6 var result = MyStatic.IsMySiteNameTypemock(fake); 7 Assert.AreEqual(true, result); 8 }
现在我们来运行测试一下看看结果
4:跳过某一个异常的方法
如果在一个方法体中要先执行一个方法(一个依赖项)然后在执行后面的代码下面我们在来看这个例子
1 public class Dependency//一个依赖项 2 { 3 public virtual void CheckSecurity(string name, string password) 4 { 5 throw new SecurityException(); 6 } 7 }
1 public class Dependency//一个依赖项 2 { 3 public virtual void CheckSecurity(string name, string password) 4 { 5 throw new SecurityException(); 6 } 7 }
1 public int Calculate(int a, int b, Dependency dependency) 2 { 3 dependency.CheckSecurity("typemock", "rules"); 4 return a + b; 5 }
1 public int Calculate(int a, int b, Dependency dependency) 2 { 3 dependency.CheckSecurity("typemock", "rules"); 4 return a + b; 5 }
然后我们进行需要跳过CheckSecurity这个会报异常的方法来看看例子
1 [TestMethod, Isolated] 2 public void FakeMethod_OnLiveObject() { 3 var dependency = new Dependency(); 4 Isolate.WhenCalled(() => dependency.CheckSecurity(null, null)).IgnoreCall();//不去管这个方法的调用 5 var classUnderTest = new ClassUnderTest(); 6 var result = classUnderTest.Calculate(1, 2, dependency); 7 Assert.AreEqual(3, result); 8 }
1 [TestMethod, Isolated] 2 public void FakeMethod_OnLiveObject() { 3 var dependency = new Dependency(); 4 Isolate.WhenCalled(() => dependency.CheckSecurity(null, null)).IgnoreCall();//不去管这个方法的调用 5 var classUnderTest = new ClassUnderTest(); 6 var result = classUnderTest.Calculate(1, 2, dependency); 7 Assert.AreEqual(3, result); 8 }
5:在未来某个方法体中创建伪对象
比喻在一个放法A中我们会依赖一个B类那么这个在内部实例化的那么我们该怎么办呢。看下面这个例子
这个外部的依赖项依然是上面的Dependency。
现在我们来修改Calculate这个方法体如下
1 public static int Calculate(int a, int b) { 2 var dependency = new Dependency(); 3 dependency.CheckSecurity("typemock", "rules"); 4 return a + b; 5 }
1 public static int Calculate(int a, int b) { 2 var dependency = new Dependency(); 3 dependency.CheckSecurity("typemock", "rules"); 4 return a + b; 5 }
我们在Calculator中直接去实例化Dependency这个对象了。
那么我们来看看怎么去注入这个伪对象
1 [TestMethod, Isolated] 2 public void FakeConstructor() { 3 var fakeHandle = Isolate.Fake.NextInstance<Dependency>();//不需要注入在未来进行创建的伪对象 4 var result = ClassUnderTest.Calculate(1, 2); 5 Assert.AreEqual(3, result); 6 }
1 [TestMethod, Isolated] 2 public void FakeConstructor() { 3 var fakeHandle = Isolate.Fake.NextInstance<Dependency>();//不需要注入在未来进行创建的伪对象 4 var result = ClassUnderTest.Calculate(1, 2); 5 Assert.AreEqual(3, result); 6 }
我们采用了NextInstance这个表示在未来的某个方法体中去创建这个伪对象。ok我们来看下测试的效果
上面就简单介绍了一个typemock的基本用法。
分类: 单元测试
时间: 2024-10-10 17:59:18