.net单元测试——常用测试方式(异常模拟、返回值测试、参数测试、数据库访问代码测试)
2014-01-27 03:30
399 查看
最近在看.net单元测试艺术,我也喜欢单元测试,今天介绍一下如何测试异常、如何测试返回值、如何测试模拟对象的参数传递、如何测试数据库访问代码。单元测试框架使用的是NUnit,模拟框架使用的是:Rhino.Mocks。
1.测试异常,可以直接对方法进行异常测试,也可以对模拟对象进行异常测试,但是,对模拟对象进行异常测试,很少用,所以,这里就介绍对方法的异常测试。请看如下代码,当用户名为空的时候,抛出异常。
测试代码如下:
这里需要特性“ExpectedException”,意思是期待抛出一个异常。这里不需要再进行断言了,抛出异常后,后面的代码也就不会执行了。
2.测试返回值,这里主要讲测试模拟对象的返回值。这里用到了一个LastCall的一个类,比较常用,一些辅助测试的功能,都在该类中。测试代码如下:
3.测试模拟对象的参数传递,当调用模拟对象时,可能需要传递参数,如果参数的值不一至时,会导致测试失败,比如:我需要传递一个字符串,其中包含了一个GUID+UserName,这里GUID可能我们无法模拟,所以,测试参数时,只需要测试UserName就可以。
方法代码如下:
测试代码如下:
这里只是测试模拟对象的参数传递。
4.测试数据库访问代码,这里提供的方法是,执行完测试代码后,对数据库进行回滚。有两种实现方式,一种是使用Rollback特性,一种是使用TransactionScope类。其实,Rollback也使用TransactionScope类。
1) Rollback特性
开始我以为Rollback是NUnit框架自带的一个特性,结果不是,需要自己编写代码,这里需要继承ITestAction接口,该接口包含BeforeTest方法和AfterTest方法。Rollback特性的代码如下:
下面是被测试的代码,这里我用了EF框架,代码非常简单,向TitleInfo表中,写入数据,该表中只有一个字段,就是title字段。如果写入成功,则返回值大于0.
使用Rollback特性进行测试。
非常简单,加入Rollback特性即可,这里不会向数据库写入记录,但是测试会成功。
2) 使用TransactionScope类测试数据访问层,该类可以实现数据库的事务操作,执行测试代码后,会对数据库的事务进行回滚,达到测试的目的,而不需要修改数据库的数据。测试代码如下:
这里加入了TransactionScope类,在Test_Insert方法执行前,会先执行Init方法,执行完Test_Insert方法后,执行Close方法,对事务进行回滚。其实Rollback只是对TransactionScope进行了封装,通过NUnit框架,很方便的实现了数据库事务的回滚。
总结:这里只是总结了常用的测试方法,如果大家还有其它的常见方法,可以分享一下,大家共同学习。
1.测试异常,可以直接对方法进行异常测试,也可以对模拟对象进行异常测试,但是,对模拟对象进行异常测试,很少用,所以,这里就介绍对方法的异常测试。请看如下代码,当用户名为空的时候,抛出异常。
public bool Valid(string userName, string passWord) { if (string.IsNullOrEmpty(userName)) throw new ArgumentNullException("userName is null"); var isValid = userName == "admin" && passWord == "123456"; Log.Write(userName); return isValid; }
测试代码如下:
[Test] [ExpectedException(typeof(ArgumentNullException))] public void Vaild_Throw_Test() { MyLogin l = new MyLogin(); l.Valid("", "123456"); }
这里需要特性“ExpectedException”,意思是期待抛出一个异常。这里不需要再进行断言了,抛出异常后,后面的代码也就不会执行了。
2.测试返回值,这里主要讲测试模拟对象的返回值。这里用到了一个LastCall的一个类,比较常用,一些辅助测试的功能,都在该类中。测试代码如下:
[Test] public void Valid_Return() { MockRepository mock = new MockRepository(); var log = mock.DynamicMock<ILog>(); using (mock.Record()) { log.WriteLog("admin"); LastCall.Return(0); } var returnValue = log.WriteLog("admin"); Assert.AreEqual(returnValue, 0); }
3.测试模拟对象的参数传递,当调用模拟对象时,可能需要传递参数,如果参数的值不一至时,会导致测试失败,比如:我需要传递一个字符串,其中包含了一个GUID+UserName,这里GUID可能我们无法模拟,所以,测试参数时,只需要测试UserName就可以。
方法代码如下:
public bool Valid_Paramter(string userName, string passWord) { Log.Write(Guid.NewGuid() + userName); return userName == "admin" && passWord == "123456"; }
测试代码如下:
[Test] public void Valid_Paramter() { MockRepository mock = new MockRepository(); var log = mock.DynamicMock<ILog>(); using (mock.Record()) { log.Write("admin"); LastCall.Constraints(Rhino.Mocks.Constraints.Text.Contains("admin")); } //这里代码如果不明白,可以看上一节,里面有说明。 MyLogin login = new MyLogin(); login.Log = log; var valid = login.Valid_Paramter("admin", "123456"); Assert.AreEqual(valid, true); mock.VerifyAll(); }
这里只是测试模拟对象的参数传递。
4.测试数据库访问代码,这里提供的方法是,执行完测试代码后,对数据库进行回滚。有两种实现方式,一种是使用Rollback特性,一种是使用TransactionScope类。其实,Rollback也使用TransactionScope类。
1) Rollback特性
开始我以为Rollback是NUnit框架自带的一个特性,结果不是,需要自己编写代码,这里需要继承ITestAction接口,该接口包含BeforeTest方法和AfterTest方法。Rollback特性的代码如下:
public class RollbackAttribute : Attribute, ITestAction { private TransactionScope transaction; public void BeforeTest(TestDetails testDetails) { transaction = new TransactionScope(); } public void AfterTest(TestDetails testDetails) { transaction.Dispose(); } public ActionTargets Targets { get { return ActionTargets.Test; } } }
下面是被测试的代码,这里我用了EF框架,代码非常简单,向TitleInfo表中,写入数据,该表中只有一个字段,就是title字段。如果写入成功,则返回值大于0.
public int Insert(string title) { testEntities db = new testEntities(); var titleInfo = new TitleInfo() { Title = title }; db.TitleInfo.Add(titleInfo); return db.SaveChanges(); }
使用Rollback特性进行测试。
[Test] [Rollback] public void Test_Insert() { DBLibrary db = new DBLibrary(); var count = db.Insert("admin"); Assert.True(count > 0); }
非常简单,加入Rollback特性即可,这里不会向数据库写入记录,但是测试会成功。
2) 使用TransactionScope类测试数据访问层,该类可以实现数据库的事务操作,执行测试代码后,会对数据库的事务进行回滚,达到测试的目的,而不需要修改数据库的数据。测试代码如下:
[TestFixture] class DBLibraryTest { TransactionScope socp; [SetUp] public void Init() { socp = new TransactionScope(); } [TearDown] public void Close() { socp.Dispose(); } [Test] public void Test_Insert() { DBLibrary db = new DBLibrary(); var count = db.Insert("admin"); Assert.True(count > 0); } }
这里加入了TransactionScope类,在Test_Insert方法执行前,会先执行Init方法,执行完Test_Insert方法后,执行Close方法,对事务进行回滚。其实Rollback只是对TransactionScope进行了封装,通过NUnit框架,很方便的实现了数据库事务的回滚。
总结:这里只是总结了常用的测试方法,如果大家还有其它的常见方法,可以分享一下,大家共同学习。
相关文章推荐
- .net单元测试——常用测试方式(异常模拟、返回值测试、参数测试、数据库访问代码测试)
- 常用的数据库访问方式
- 分析总结Spring管理Hibernate中Dao层访问数据库常用方式(附SSH的jar包)
- 06-编写Hibernate API编写访问数据库的代码,使用Junit进行测试
- MySQL 数据库访问方式,以及jar包版本太高出现的访问数据库异常问题
- java application 应用程序 使用JDBC proxool 两种方式连接数据库 测试程序代码
- java application应用程序 使用JDBC和proxool两种方式连接数据库 的测试程序代码
- java application应用程序 使用JDBC和proxool两种方式连接数据库 的测试程序代码
- MyBatis, MyBatis-Spring 常用访问数据库的方式
- 敏感数据加密保护和数据库访问方式的测试内容
- ADO.NET的学习笔记(一)--数据库连接及常用的数据库访问方式
- Struts2_13_访问WEB元素_2(最常用控制反转的方式)
- 以编程方式访问数据库
- 当读取数据,而未将处理后的数据提交会数据库时,如果数据库发上更改,将会引发LINQ异常,处理方式有:
- 数据库常用懒得打代码备份
- php 访问数据库的三种方式
- C#项目图文说明 不允许所请求的注册表访问权 异常的一种解决方式
- 用悲观并发方式处理数据库并发冲突以保证数据一直性的代码处理方法
- spring结合hibernate访问数据库方式的比较
- 独占的方式读写文件,经jmeter1000个线程并发访问测试没问题