遗留代码的测试

遗留代码的测试

在大多时候代码的测试很难,因为很多代码无法进行参数注入,那么这个时候有一款不受限的隔离框架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

遗留代码的测试的相关文章

对历史遗留代码的维护和再开发

一.时间宽松时的代码维护 对于新人,一般都会留出一段时间进行代码的接手,那么对于如何处理接到手中的代码,是不是只是看看代码.写写心得,还是能够利用这段空闲时间,煅炼提升自己,我期望是后者,结合公司部门的情况,对这种情况进行个人阐释: 1.对现有代码的熟悉.若是对拿到手中的代码,都不知道是做什么的,有什么用,可能就什么意义也没有,后面的也不用看了. 2.加入或者补充测试用例,若是没有测试用例,后面的重构基本上是没办法进行判断是否正确的. 3.用测试用例对代码进行测试,以期达到相关效果和理解代码逻辑

应用MVP模式对遗留代码进行重构

AV(Autonomous View)自治视图 在面向终端用户的应用中,都需要一个可视化的UI来与用户交互.这个UI称为View视图. 在早期,我们习惯将所有前台的逻辑,与视图揉在一起,称为AV自治视图. 这些逻辑包括:数据呈现(Display),用户动作的扑捉与响应,数据存储等. 在.Net的Winform和ASP.NET Web Form中,采用的都是事件驱动模型. AV是将所有UI相关的逻辑都注册到视图本身,或者视图元素对应的事件上. 人机交互应用的3个关注点. 数据在UI上的展示. UI

跟遗留代码打交道:干掉顽固漏洞的简单方式

事实证明,跟遗留代码打交道未必需要花费数天时间去研究晦涩难懂的注释.要想找到并修复漏洞,开发者可采用简单的测试工具来对问题抽丝剥茧. 跟遗留代码打交道会是比较困难的,尤其是如果代码是由某位不知道名字的程序员用一种不熟悉的语言编写的话.但跟据Mob Programming 的R Jason Kerney 和Llewellyn Falco的说法,遗留应用中的bug是可以相对迅速地发现和修补好的,这个过程只需要若干相当直截了当的技巧. "我通常是没有机会去理解(遗留)代码的,所以我必须想出办法在不理解

重构遗留代码(1):金牌大师

旧代码,丑陋的代码,复杂的代码,意大利面条似的代码,鬼话废话……就是四个字:遗留代码.这是一个系列文章,将有助于你处理并解决它. 在理想的世界中,你只会写新代码.你会把代码写得既漂亮又完美.你将永不会再看你的代码,并且你将永远不会维护一个有十年之久的项目.在理想的世界中… 不幸的是,我们生活在现实的而非理想的世界.我们必须理解修改和增强年代久远的代码这件事.我们必须处理遗留代码.那么你还在等什么?让我们一头扎进第一篇教程,拿着代码,读懂一点点,并为了我们日后的修改编织一张安全网. 遗留代码的定义

遗留代码

关键词:遗留代码,代码修改,测试 概述 从其他人或者其他版本获得的代码. 特点 架构设计差 代码风格不一致 文档少和模糊 非常有价值,成功代码 修改遗留代码原因 新功能 Bug 重构 优化 修改 Risky change 修改风险 What changes do we have to make? 哪些是必须修改的内容 How will we know that we've done them correctly? 修改正确吗 How will we know that we haven't br

对遗留代码的解依赖技术

参数适配 使用场景:当无法对一个参数的类型使用接口提取,或者该参数难以被"伪装"时. 例如,该参数的类型是一个含有很多方法的接口类型.在进行单元测试时必须编写一个实现该接口的实现类. 可以使用Mock. 问题:从维护的角度来看,传递了一个宽接口,而其实方法内部只使用了该接口的部分契约. 所以,应该尽量使用窄接口来替代宽接口. 分解出方法对象 使用场景:若方法规模太大,或者使用了实例变量或者其他方法. 将大方法移到一个新类中,因为该类仅含有一个方法成员,所以称为方法对象. 可以方便地对方

实验二:关于梭哈游戏的代码的测试

实验二:关于梭哈游戏的代码的测试 一.题目简介 Github基本源代码控制方法 利用Junit4进行程序模块的测试,回归测试 编码规范的考量 C/Java等基本程序设计语言的运用. (考虑到有些同学的基础参差不齐) 实现纸牌游戏梭哈 二.个人github地址 https://github.com/qingfengsuixin/test/blob/master/ShowHand 三.所设计的模块测试用例.测试结果截图: package com.langsin.text2; import java.

在线捉鬼游戏开发之三 - 代码与测试(鬼讨论、鬼投票)

-----------回顾分割线----------- 此系列旨在开发类似“谁是卧底+杀人游戏”的捉鬼游戏在线版,记录从分析游戏开始的开发全过程,通过此项目让自己熟悉面向对象的SOLID原则,提高对设计模式.重构的理解. 索引目录: 0. 索引(持续更新中) 1. 游戏流程介绍与技术选用 2. 设计业务对象与对象职责划分(1)(图解旧版本) 3. 设计业务对象与对象职责划分(2)(旧版本代码剖析) 4. 设计业务对象与对象职责划分(3)(新版本业务对象设计) 5. 业务对象核心代码编写与单元测试

在线捉鬼游戏开发之三 - 代码与测试(玩家发言)

-----------回顾分割线----------- 此系列旨在开发类似“谁是卧底+杀人游戏”的捉鬼游戏在线版,记录从分析游戏开始的开发全过程,通过此项目让自己熟悉面向对象的SOLID原则,提高对设计模式.重构的理解. 索引目录: 0. 索引(持续更新中) 1. 游戏流程介绍与技术选用 2. 设计业务对象与对象职责划分(1)(图解旧版本) 3. 设计业务对象与对象职责划分(2)(旧版本代码剖析) 4. 设计业务对象与对象职责划分(3)(新版本业务对象设计) 5. 业务对象核心代码编写与单元测试