- 浏览: 246970 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (293)
- web (1)
- [随笔分类]项目管理 (30)
- [随笔分类]WCF (14)
- 未分类 (1)
- [随笔分类]Linq (4)
- [随笔分类]C#基础 (24)
- 项目 (1)
- [网站分类]3.非技术区(技术之外的文章,但不要涉及任何政治内容) (8)
- [网站分类]1.首页原创精华.NET区(包含架构设计、设计模式)(对首页文章的要求:原创、高质量、经过认真思考并精心写作) (9)
- [随笔分类]Ubuntu (4)
- ASP.Net (1)
- [网站分类]2..NET新手区(用于发表不合适发表在首页的.NET技术文章,包括小经验、小技巧) (30)
- [随笔分类]ASP.NET MVC (20)
- [随笔分类]ASP.NET (3)
- [随笔分类]程序员厨房 (4)
- [随笔分类]英语学习 (28)
- [网站分类]4.其他技术区 (1)
- [随笔分类]Silverlight (12)
- [随笔分类]CodeSmith (8)
- [随笔分类]其他 (4)
- [随笔分类]Ruby (4)
- [发布至博客园首页] (34)
- [网站分类]其他技术区 (3)
- [随笔分类]Ruby on Rails (2)
- [网站分类].NET新手区 (33)
- [随笔分类]TDD (1)
- [随笔分类]不谈技术 (2)
- [网站分类]非技术区 (7)
最新评论
-
yicone:
You make a mistake when paste t ...
WCF步步为营(一):简单示例 -
jinweijie:
你好,这个实现不错,但是在用了scriptmanager以后就 ...
在服务器端保存ViewState
解决的问题:方法内部new的对象在测试时希望能够用mock对象去代替。
问题:以下方法可以解决,但是很是丑陋,各位大侠是否有更好的方法?
描述:如果说把内部的方法放到类的一个公开成员变量,或者放到方法的参数里,我的意见是公开了不应该公开的东西。
使用第三方的类库: Mock工具 Rhino.Mocks, IOC: Castle.Windsor
1. 现在我又这么一段代码,我想测试Math内部这两个方法
public class Math
{
public long MathAdd(int a, int b)
{
Calc c = new Calc();
return c.Add(a, b);
}
public long MathAdd2Price(int a)
{
Calc c = new Calc();
return c.AddCount(a) + c.count;
}
}
public class Calc
{
public int count = 0;
public long Add(int a, int b)
{
return a + b;
}
public long AddCount(int num)
{
return count + num;
}
}
2. 我们看到,由于是在内部new的对象,我们就对Calc类产生了很大的依赖,于是我想到注入一个对像,下面是我的设计
public class ContainerFactory
{
public static IWindsorContainer container;
public bool IsDebug = false;
private static readonly ContainerFactory instance = new ContainerFactory();
public static ContainerFactory Instance
{
get
{
return instance;
}
}
private ContainerFactory()
{
AddAllCompent();
}
private void AddAllCompent()
{
if (container == null)
{
container = new WindsorContainer();
//此处职位演示,未使用接口
container.AddComponentWithLifestyle<Calc>("Calc", LifestyleType.Transient); }
}
}
这样我们的Math类可改成这样
public class Math
{
public long MathAdd(int a, int b)
{
// Calc c = new Calc();
Calc c =(Calc) ContainerFactory.container["Calc"];
return c.Add(a, b);
}
public long MathAdd2Price(int a)
{
Calc c = (Calc)ContainerFactory.container["Calc"];
return c.AddCount(a) + c.count;
}
}
3. 但是,我们如何在测试中用我们Mock的对象代替真实的对象呢?下面是我想的一个自己也认为不好的方法,但能凑活着用
public class ContainerFactory
{
private IWindsorContainer container;
public bool IsDebug = false;
private static readonly ContainerFactory instance = new ContainerFactory();
public static ContainerFactory Instance
{
get
{
return instance;
}
}
private ContainerFactory()
{
AddAllCompent();
}
private void AddAllCompent()
{
if (container == null)
{
container = new WindsorContainer();
//此处职位演示,未使用接口
container.AddComponentWithLifestyle<Calc>("Calc", LifestyleType.Transient); }
}
#region Calc
private Calc DebugCalc;
public Calc Calc
{
get
{
if (IsDebug && DebugCalc != null)
{
return DebugCalc;
}
else
{
return (Calc)container["Calc"];
}
}
set
{
// just for test, for mock object
if (IsDebug)
{
DebugCalc = value;
}
else
{
throw new Exception("just for test");
}
}
}
#endregion
}
修改我们的类
public class Math
{
public long MathAdd(int a, int b)
{
// Calc c = new Calc();
Calc c = ContainerFactory.Instance.Calc;
return c.Add(a, b);
}
public long MathAdd2Price(int a)
{
Calc c = ContainerFactory.Instance.Calc;
return c.AddCount(a) + c.count;
}
}
这样我们来看我们通过了测试的代码
[TestClass()]
public class MathTest
{
[TestMethod()]
public void MathAddTest()
{
Math m = new Math();
// 想让真实代码内部,使用的是Mock的对象
// Arrange
MockRepository mocks = new MockRepository();
Calc mockCalc = mocks.Stub<Calc>();
mockCalc.count = 5;
ContainerFactory.Instance.IsDebug = true; //这句很重要
ContainerFactory.Instance.Calc = mockCalc;
mocks.ReplayAll();
// Act
Assert.AreEqual(m.MathAdd(5, 5), 10);
Assert.AreEqual(mockCalc.AddCount(6), 11);
mocks.VerifyAll();
Calc mockCalc2 = mocks.Stub<Calc>();
mocks.ReplayAll();
// 这里有问题,我们希望他是7,但实际是12,因为需要测试中的和实际代码用同一个对象,
// 他保留上次的状态count的值5
Assert.AreEqual(mockCalc.AddCount(7), 12);
mocks.VerifyAll();
}
[TestMethod]
public void MathAddTestActual()
{
//这里测试实际使用代码,没用Mock
Math m = new Math();
Assert.AreEqual(m.MathAdd(5,6), 11);
Assert.AreEqual(m.MathAdd2Price(9), 9);
Calc c = ContainerFactory.Instance.Calc;
Assert.AreEqual(c.AddCount(5), 5);
c.count = 20;
Assert.AreEqual(c.AddCount(5), 25);
Calc d = ContainerFactory.Instance.Calc;
Assert.AreEqual(d.AddCount(30), 30);
Assert.AreEqual(c.count, 20);
Assert.AreEqual(d.count, 0);
}
}
总结:这样可以不使用用public的类成员变量,不用通过方法参数注入注入对象
问题: ContainerFactory代码较多,测试时需要设标志。
其它的问题: 等待高人指出,谢谢!
发表评论
-
ASP.NET MVC源码现在可以下载了(翻译)
2008-03-22 09:44 902上个月我在blog里介绍了ASP.NET MVC Roadm ... -
ASP.NET MVC+LINQ开发一个图书销售站点
2008-03-29 17:12 1296园子里已经有很多人讲解了其理论知识,网上也有不少示例,但是很多 ... -
Linq to SQL Dynamic 动态查询
2008-04-01 15:09 1016在开发中我们常需要使用动态的条件来组合查询,scotte博客里 ... -
使用ASP.NET 3.5 Extensions管理浏览器历史:使用服务器端
2008-04-08 13:15 594我们知道当我们使用ASP.NET AJAX的一些方便的服务端控 ... -
客户比产品更重要
2008-04-12 15:49 605发现博客园里99%都是技术文章,很少有管理的经验分享 ... -
WPF 全球化和本地化(图解)
2008-04-12 16:15 795当您将自己的产品限制为只能通过一种语言使用时,您便将潜在的客户 ... -
项目经理如何参与任务管理
2008-04-14 17:55 649每个项目经理可能都会 ... -
.NET环境下每日集成
2008-04-24 17:36 1352本系列主要介绍了.Net环境下如何使用CruiseContro ... -
项目经理虚拟管理客户
2008-05-28 11:26 530项目经理做项目时经常 ... -
从中国男足看项目管理
2008-06-16 11:39 404国足1:2 不敌伊拉克后,彻底无缘本届世界杯,我想比赛时和赛后 ... -
敏捷的 "道"
2008-11-19 14:10 479本文摘要 敏捷的路上 ... -
在服务器端保存ViewState
2008-11-20 16:51 5501.比较 Asp.net 的一个强大的功能就是ViewStat ... -
TDD实验2:使用VSTS 的单元测试功能
2008-12-10 08:25 768我们要实现的功能是,发工资时自动向我们发送邮件,如果工资少于1 ... -
Web测试:Selenium使用
2008-12-23 10:49 1587<style> .confluenceTable ... -
谈软件协作:君子和而不同,小人同而不和
2008-12-31 18:39 670我们知道现在的软件开 ... -
如何进行ASP.NET MVC 的测试
2009-01-05 00:48 1308本文参考了http://stephenwalther.com/ ... -
如何使ASP.NET MVC Controller易测试呢?
2009-01-05 23:25 945昨天那篇文章如何进行ASP.NET MVC 的测试,虽然通过自 ... -
ASP.NET MVC AJAX的调用
2009-01-10 08:21 3728在ASP.NET MVC beta中我们可以使用Ajax.Be ... -
IIS7 配置ASP.NET 2.0, WCF, ASP.NET MVC
2009-01-16 17:50 4579ASP.NET 2.0 部署 1.首先打开win7 的特性,路 ... -
一步一步学Ruby(一): Ruby介绍
2009-01-21 00:16 757文章摘要 Ruby是如何来的 准备 ...
相关推荐
pos-oop-tdd 使用 TDD 创建面向对象的 pos 项目。
TDD:通过大量测试寻找最优解决方案.docx
nodejs-tdd-learn 使用NodeJS和TDD进行项目 :test_tube: :beaming_face_with_smiling_eyes:
tdd1t 支持您的TDD努力的机器人 一个GitHub应用程序,用于根据“拉取请求”中提交的测试检查功能规范。 设置 # Install dependencies npm install # Run the bot npm start 贡献 如果您对如何改进tdd1t有任何建议,...
GSM TDD 板振说明及分析方法、解决方法总结
TDD(Test-Driven Development) 测试驱动开发是敏捷开发中的一项核心实践和...TDD首先考虑使用需求(对象、功能、过程、接口等),主要是编写测试用例框架对功能的过程和接口进行设计,而测试框架可以持续进行验证。
java-hello-tdd:使用Java的TDD
tdd-exercise:一些学习TDD的练习
演示-tdd1Spring启动演示测试驱动开发
tdd 简单的TDD实现
Spruce XP文档更新! Spruce XP是一个体验平台,旨在创建难忘的体验和持久的关系。
Test Driven: Practical TDD and Acceptance TDD for Java Developers (PDF英文版)
FizzBuzz TDD 关于 研究测试驱动开发(TDD)的项目。 锻炼: 编写一个程序,打印从1到100的数字。但是,对于三个打印数字“ Fizz”(而不是数字)的倍数,以及五个打印“嗡嗡声”的倍数。 对于三和五的倍数的...
无论如何,我想通过添加测试驱动开发(TDD),一些JavaScript和部署使本教程更进一步。 这篇文章就是该教程。 请享用。 另外,如果您一般不熟悉Flask和/或Web开发,那么掌握以下基本概念很重要: GET和POST请求...
tdd-start:TDD첫
spring-boot-tdd-example:tdd学习spring入门demo
php-tdd-unit:使用TDD策略和单元测试编写PHP
React TDD工作坊 WIP-这是我的 欢迎来到我的React TDD研讨会! 入门 npm i npm test 观看模式: 1号航站楼: npm start 2号航站楼: npm run test:watch 这个研讨会是关于什么的? 我们将使用React + Jest + ...
tdd_webapp:创建测试Web应用程序以理解TDD方法
TDD_dice:TDD骰子卷