- 浏览: 257020 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (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 941上个月我在blog里介绍了ASP.NET MVC Roadm ... -
ASP.NET MVC+LINQ开发一个图书销售站点
2008-03-29 17:12 1324园子里已经有很多人讲解了其理论知识,网上也有不少示例,但是很多 ... -
Linq to SQL Dynamic 动态查询
2008-04-01 15:09 1053在开发中我们常需要使用动态的条件来组合查询,scotte博客里 ... -
使用ASP.NET 3.5 Extensions管理浏览器历史:使用服务器端
2008-04-08 13:15 620我们知道当我们使用ASP.NET AJAX的一些方便的服务端控 ... -
客户比产品更重要
2008-04-12 15:49 659发现博客园里99%都是技术文章,很少有管理的经验分享 ... -
WPF 全球化和本地化(图解)
2008-04-12 16:15 826当您将自己的产品限制为只能通过一种语言使用时,您便将潜在的客户 ... -
项目经理如何参与任务管理
2008-04-14 17:55 678每个项目经理可能都会 ... -
.NET环境下每日集成
2008-04-24 17:36 1387本系列主要介绍了.Net环境下如何使用CruiseContro ... -
项目经理虚拟管理客户
2008-05-28 11:26 559项目经理做项目时经常 ... -
从中国男足看项目管理
2008-06-16 11:39 431国足1:2 不敌伊拉克后,彻底无缘本届世界杯,我想比赛时和赛后 ... -
敏捷的 "道"
2008-11-19 14:10 508本文摘要 敏捷的路上 ... -
在服务器端保存ViewState
2008-11-20 16:51 5741.比较 Asp.net 的一个强大的功能就是ViewStat ... -
TDD实验2:使用VSTS 的单元测试功能
2008-12-10 08:25 797我们要实现的功能是,发工资时自动向我们发送邮件,如果工资少于1 ... -
Web测试:Selenium使用
2008-12-23 10:49 1622<style> .confluenceTable ... -
谈软件协作:君子和而不同,小人同而不和
2008-12-31 18:39 706我们知道现在的软件开 ... -
如何进行ASP.NET MVC 的测试
2009-01-05 00:48 1340本文参考了http://stephenwalther.com/ ... -
如何使ASP.NET MVC Controller易测试呢?
2009-01-05 23:25 984昨天那篇文章如何进行ASP.NET MVC 的测试,虽然通过自 ... -
ASP.NET MVC AJAX的调用
2009-01-10 08:21 3767在ASP.NET MVC beta中我们可以使用Ajax.Be ... -
IIS7 配置ASP.NET 2.0, WCF, ASP.NET MVC
2009-01-16 17:50 4636ASP.NET 2.0 部署 1.首先打开win7 的特性,路 ... -
一步一步学Ruby(一): Ruby介绍
2009-01-21 00:16 792文章摘要 Ruby是如何来的 准备 ...
相关推荐
1. **Mock的基本概念**:Mock对象是模拟真实对象的行为和响应的假对象。它们用于代替真实的对象,以减少测试中的依赖性和复杂性。Mock对象可以预设返回值,记录方法调用,以及验证方法是否按预期被调用。 2. **单元...
1. **减少对外部依赖的直接调用**:Mock对象允许测试人员在不依赖实际数据库连接、网络请求或硬件设备的情况下进行测试,提高了测试的可执行性和速度。 2. **增强测试的可预测性**:通过Mock对象,可以预设特定的...
在C/C++项目中应用测试驱动开发(TDD)的方法,从单元测试到集成测试,详尽介绍了测试的基础、框架选择、实际应用及最佳实践。文章首先阐述了TDD的核心理念及其优势,包括提升代码质量、减少错误和改进设计等。接着...
面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它基于“对象”的概念,将数据和操作数据的方法封装在一起。在本文中,我们将深入探讨如何使用Test-Driven Development(TDD,测试驱动开发)...
Mock是测试驱动开发(TDD)和行为驱动开发(BDD)中的关键元素。它用于模拟那些难以控制或者不存在的外部系统,如网络API、数据库访问等,使得测试更为独立和可控。通过Mock,我们可以在不依赖真实服务的情况下,确保...
1. **什么是Mock对象**:Mock对象是模拟真实对象行为的替代品,它们可以预定义返回值、抛出异常或记录方法调用,以符合测试需求。 2. **Mocking框架**:在Java中,有Mockito、PowerMock等框架;在JavaScript中,有...
在软件测试领域,特别是测试驱动开发(Test-Driven Development, TDD)中,Mock 对象和 Fake 对象是两个容易混淆的概念。下面详细介绍两者的区别: - **Fake 对象**:具有实际的工作逻辑实现,但通常采用一些简化的...
1. **隔离性**:Mock对象确保测试只关注待测试代码,避免了因依赖其他组件导致的复杂性。 2. **可预测性**:预设Mock对象的行为,可以准确地控制测试结果。 3. **验证**:通过验证方法调用,确认代码是否正确地使用...
Mock对象是一种在测试环境中模拟其他对象行为的对象,主要用于隔离被测试对象与外部环境的交互,从而聚焦于测试对象本身的行为。通过EasyMock,开发者可以轻松创建和配置mock对象,以满足单元测试的需求。 例如,在...
**7.34 Tip:Document 对象** - **介绍**: DOM 核心 API 的一部分,代表整个 XML 文档。 - **方法**: - 获取根节点 - 创建节点 - 添加节点 **7.35 Tip:节点对象** - **类型**: - 元素节点 - 属性节点 - 文本...
标题中的"TDD"指的是Test-Driven Development,即测试驱动开发,是一种软件开发方法论,强调在编写实际代码之前先编写测试用例。这种方法的核心理念是通过编写测试来定义需求,确保代码的质量和功能完整性。TDD的...
Mockito是一款广泛应用于Java开发中的测试驱动开发(TDD)工具,它允许开发者创建和配置模拟对象,以便在测试中隔离代码并验证特定方法的行为。这本书详细介绍了如何有效地利用Mockito来编写整洁、可维护的测试代码...
《Test Driven: Practical TDD and Acceptance TDD for Java Developers》是一本专注于Java开发者进行测试驱动开发(TDD)和验收测试驱动开发(Acceptance TDD)的专业书籍。这本书以PDF英文版的形式提供,旨在帮助...
标题 "TDD:在JAVA中学习TDD @odd-e" 提到的是Test-Driven Development(测试驱动开发,简称TDD)在Java编程语言中的实践。TDD是一种软件开发方法论,强调先编写测试用例,然后编写刚好足够通过测试的生产代码。这种...
3. MockObjects:MockObjects是早期的模拟对象框架,它的设计理念对后来的模拟框架产生了深远影响。虽然现在它已经被其他更现代的框架所替代,但理解它的概念和用法对于理解模拟对象在TDD中的作用仍然很有价值。 在...
3. **验证调用**:检查Mock对象的方法是否按预期被调用,以及调用参数是否正确。 4. **集成测试框架**:可能与常见的Python测试框架如unittest、pytest等无缝集成,简化测试代码的编写。 5. **版本管理**:2.2.0版本...
**Ruby-TDD实战:Test Driven Development in Action** 在软件开发领域,Test-Driven Development(TDD)是一种编程实践,它强调先编写测试用例,然后编写满足这些测试的最小功能代码。Ruby作为一种动态、灵活的...