在大多时候代码的测试很难,因为很多代码无法进行参数注入,那么这个时候有一款不受限的隔离框架TypeMock供你使用,不过遗憾这款软件是付费的一个隔离框架,有15天的免费使用权,如果能解决你现有的问题我想这份费用并不能算多。TypeMock的官方下载http://www.typemock.com/。下面开始看看TypeMock是怎么样使用的。
1:伪造一个静态的方法来看一个例子
被测试的静态方法
[flash=500,400]http://s1.knowsky.com/20160211/or5tfgb4vcx23.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/1w2wvbkbchy23.gif[/flash]publicstaticintDoSomethingSpecialOnALeapYear()
{if((DateTime.Now.Month ==3) && (DateTime.Now.Day ==29))return100;return0;
}
DoSomethingSpecialOnALeapYear
测试方法
[flash=500,400]http://s1.knowsky.com/20160211/or5tfgb4vcx23.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/1w2wvbkbchy23.gif[/flash]1[TestMethod, Isolated]2publicvoidFakingDateTime()3{4Isolate.WhenCalled(() => DateTime.Now).WillReturn(newDateTime(2016,3,29));//当调用当前时间的时候会返回指定的时间5intresult =MyStatic.DoSomethingSpecialOnALeapYear();6Assert.AreEqual(100, result);7}
FakingDateTime
2:伪造一个sealed的类
被测试的静态方法
[flash=500,400]http://s1.knowsky.com/20160211/or5tfgb4vcx23.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/1w2wvbkbchy23.gif[/flash]1publicstaticboolSignedIn {get;set; }23publicstaticboolSignOut(HttpContext current)4{5if(SignedIn)6{7HttpsessionState session =current.Session;8session.Abandon();9returntrue;10}11returnfalse;12}
SignOut
如果我们要保证上面的方法能不在依赖HttpContext 那么我们必须要注入这个依赖我们看测试代码
[flash=500,400]http://s1.knowsky.com/20160211/or5tfgb4vcx23.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/1w2wvbkbchy23.gif[/flash]1[TestMethod, Isolated]2publicvoidFakingHttpContext()3{4varfakeHttp = Isolate.Fake.Instance<HttpContext>();//需要注入的伪对象5MyStatic.SignedIn =true;6varresult =MyStatic.SignOut(fakeHttp);7Assert.AreEqual(true, result);8}
FakingHttpContext
3:重写伪造类中的方法
如果一些类现在要按照我们的需要来返回相应的值我们来看看下面这个例子
[flash=500,400]http://s1.knowsky.com/20160211/or5tfgb4vcx23.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/1w2wvbkbchy23.gif[/flash]1publicstaticboolIsMySiteNameTypemock(PRocess process)2{3varname =process.MachineName;4if(process.MainModule.Site.Name.StartsWith("Typemock"))5returntrue;6else7returnfalse;8}
IsMySiteNameTypemock
为了上面的程序正常工作那么我们必须需要通过site.Name以Typemock开始所以在测试中我们必须这么做
[flash=500,400]http://s1.knowsky.com/20160211/or5tfgb4vcx23.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/1w2wvbkbchy23.gif[/flash]1[TestMethod, Isolated]2publicvoidSetBehaviorOnChainExample()3{4varfake = Isolate.Fake.Instance<Process>();5Isolate.WhenCalled(() => fake.MainModule.Site.Name).WillReturn("Typemock rocks");//设置Site.Name6varresult =MyStatic.IsMySiteNameTypemock(fake);7Assert.AreEqual(true, result);8}
SetBehaviorOnChainExample
现在我们来运行测试一下看看结果
[flash=500,400]http://s1.knowsky.com/20160211/5r1hy14njjf23.png[/flash]
4:跳过某一个异常的方法
如果在一个方法体中要先执行一个方法(一个依赖项)然后在执行后面的代码下面我们在来看这个例子
[flash=500,400]http://s1.knowsky.com/20160211/or5tfgb4vcx23.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/1w2wvbkbchy23.gif[/flash]1publicclassDependency//一个依赖项2{3publicvirtualvoidCheckSecurity(stringname,stringpassWord)4{5thrownewSecurityException();6}7}
Dependency
[flash=500,400]http://s1.knowsky.com/20160211/or5tfgb4vcx23.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/1w2wvbkbchy23.gif[/flash]1publicintCalculate(inta,intb, Dependency dependency)2{3dependency.CheckSecurity("typemock","rules");4returna +b;5}
Calculate
然后我们进行需要跳过CheckSecurity这个会报异常的方法来看看例子
[flash=500,400]http://s1.knowsky.com/20160211/or5tfgb4vcx23.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/1w2wvbkbchy23.gif[/flash]1[TestMethod, Isolated]2publicvoidFakeMethod_OnLiveObject() {3vardependency =newDependency();4Isolate.WhenCalled(() => dependency.CheckSecurity(null,null)).IgnoreCall();//不去管这个方法的调用5varclassUnderTest =newClassUnderTest();6varresult = classUnderTest.Calculate(1,2, dependency);7Assert.AreEqual(3, result);8}
FakeMethod_OnLiveObject
5:在未来某个方法体中创建伪对象
比喻在一个放法A中我们会依赖一个B类那么这个在内部实例化的那么我们该怎么办呢。看下面这个例子
这个外部的依赖项依然是上面的Dependency。
现在我们来修改Calculate这个方法体如下
[flash=500,400]http://s1.knowsky.com/20160211/or5tfgb4vcx23.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/1w2wvbkbchy23.gif[/flash]1publicstaticintCalculate(inta,intb) {2vardependency =newDependency();3dependency.CheckSecurity("typemock","rules");4returna +b;5}
Calculate
我们在Calculator中直接去实例化Dependency这个对象了。
那么我们来看看怎么去注入这个伪对象
[flash=500,400]http://s1.knowsky.com/20160211/or5tfgb4vcx23.gif[/flash][flash=500,400]http://s1.knowsky.com/20160211/1w2wvbkbchy23.gif[/flash]1[TestMethod, Isolated]2publicvoidFakeConstructor() {3varfakeHandle = Isolate.Fake.NextInstance<Dependency>();//不需要注入在未来进行创建的伪对象4varresult = ClassUnderTest.Calculate(1,2);5Assert.AreEqual(3, result);6}
FakeConstructor
我们采用了NextInstance这个表示在未来的某个方法体中去创建这个伪对象。ok我们来看下测试的效果
[flash=500,400]http://s1.knowsky.com/20160211/jnyxa2fezdh23.png[/flash]
上面就简单介绍了一个typemock的基本用法。