天高任鸟飞, 海阔凭鱼跃
海粟007

 

关键字:NUnit 单元测试 VS2005 SQL Server 数据库
         好多人都在用NUnit测试,我也是其中一员,但是我想许多人也遇到过和我一样的困难,会者不难难者不会,我想我遇到的这些困难如何解决的给大家分享一下,也能避免大家少走些弯路。

       如果您还不了解NUnit,您可以点击下载一个关于NUnit的中文帮助文档,我这里要说明的是,这边文章不是我翻译的,是由NUnit专家 Dorian Deng  翻译,只不过我是把它整理成了PDF文档供大家下载。 

        大家知道,单元测试的优点之一就是可以反复测试,但是对应数据库的单元测试怎么办呢。新增一条记录后然后再删除调,Update一条记录后在Update回来,关键是Update回来原来的数据是什么,在测试前保存,我想这不是一个好的方案。有人建议为资料库的单元测试建立一个专门测试的数据库,我感觉这也不是一个好的方案,因为新增一条记录你还必须自己控制删除,否则在新增记录的时候还是会导致测试失败,因为已经存在了相关记录。因此这也就是我要引出的主角了“EnterpriseServices”组件。

        网上也有不少关于他测试实现单元测试的方法。我看了一下,其实都是千篇一律来自同一文档,最关键的是vs003的,我在Vs2005上进行编译的时候,总是测试不过去,所以我感觉才有必要写这篇文章了。闲言少叙,还是转入正题吧。


 环境:VS2005、NUnit(我用的2.4.6)、SQL Server(数据库测试当然必不可少,我用的SQL Server2000)

实做:
第一步:首先建立一个新工程AccountTest(这是我给部门人员做演示的时候用的专案,大家将就一下)。
第二步:为此专案添加EnterpriseServices组件。当然作单元测试,也应该添加上NUnit框架


第三步:编写测试基础类
            using System;
using System.Collections.Generic;
using System.Text;
using System.EnterpriseServices;
using NUnit.Framework;
using System.Runtime.InteropServices;
using System.Data.SqlClient;
namespace Bank
{
/// 
/// 這是一個測試各種单元测试的基礎類,所有的要操作數據庫的測試類都從它繼承
/// 這樣就能保證所有的測試操作無論是新增、修改、刪除都能順利測試成功,但是并吧產生任何垃圾數據
/// 也不會修改任何實際運行的數據庫
/// 
[Transaction(TransactionOption.Required)]
[TestFixture]
public class DatabaseFixture : ServicedComponent
{
protected SqlConnection Connect = null;
/// 
/// 构造函数
/// 
public DatabaseFixture()
{
}
/// 
/// 本属性标识此测试方法结束后调用,所有事务的撤销工作都是由它来实现的
/// 
[TearDown]
public void TransactionTearDown()
{
if (ContextUtil.IsInTransaction)
{
ContextUtil.SetAbort();
}
}
/// 
/// 我在这里建立了数据库链接,其实不建立也行
/// 
[SetUp]
public void SetFirst()
{
try
{
Connect = new SqlConnection("Integrated Security=SSPI;Persist Security Info=False;User ID=sa;Initial Catalog=NorthWind;Data Source=127.0.0.1");
Connect.Open();
}
catch (Exception ex)
{
}
}
}
}
第四步: 创建签名Key
调用命令行程序(路径=系统盘:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\) sn.exe -k mytest.snk
然后把创建好的mytest.snk加入的工程中。设置参见下图(选中工程右键--Properties--Signning)

第五步:创建单元测试文件(代码如下)
         using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using System.Data;
using System.Data.SqlClient;
namespace Bank
{
[TestFixture]
public class DataTest: DatabaseFixture
{
/// 
/// 这个就是我建立的测试方法,大家发现反复执行,也不会实际把数据新增到数据库中
/// 
[Test]
public void InsertTest()
{
string SQL = "insert Categories(CategoryName, Description) values('测试类型', '测试类型描述')";
Assert.IsTrue(ExecSQLNoQuery(SQL));     //如果新增失败这行代码测试无法通过
//执行查询,看是否真的新增到数据库
DataSet ds = QueryResult("select * from Categories where CategoryName='测试类型'");
//下面两句可以测试是否真的添加到了数据库
Assert.IsNotNull(ds);
Assert.AreEqual(1, ds.Tables[0].Rows.Count);
//测试新增的数据和是否正确
StringAssert.IsMatch("测试类型描述FF", ds.Tables[0].Rows[0]["Description"].ToString());
}
/// 
/// 执行没有返回结果的SQL语句
/// 
protected bool ExecSQLNoQuery(string SQL)
{
SqlCommand Command = new SqlCommand();
Command.Connection = Connect;
Command.CommandType = CommandType.Text;
Command.CommandText = SQL;
bool retFlag = false;
try
{
Command.ExecuteNonQuery();
retFlag = true;
}
catch (Exception ex)
{
}
finally
{
Command.Dispose();
}
return retFlag;
}
/// 
/// 提供SQL语句返回查询结果
/// 
protected DataSet QueryResult(String SQL)
{
SqlCommand Command = new SqlCommand();
Command.Connection = Connect;
Command.CommandType = CommandType.Text;
Command.CommandText = SQL;
SqlDataAdapter Adapter = new SqlDataAdapter(Command);
DataSet ds = new DataSet();
bool retFlag = false;
try
{
Adapter.Fill(ds);
retFlag = true;
}
catch (Exception ex)
{
}
finally
{
Adapter.Dispose();
Command.Dispose();
}
return retFlag == true ? ds : null;
}
}
}
第六步:编译成功,进行测试。
        你可以在选中工程右键--Properties--debug--start external program选中UNit程序(这种情况可以进入调试状态跟踪运行),你也可以直接执行UNit测试程序加载刚才编译的dll进行测试。
        错误出现了如下图,这个错误捆扰了好一天多的时间,主要是由于在2005下以前也没有使用过EnterpriseServices的经验。  

        我一开始怀疑是不是网上的例子是不是本身有问题呢,我是按照例子亦步亦趋的做的,唯一的区别就是vs003和vs005的区别,最后我在Vs2003下试验了一下,能正常通过。我想要么是VS2005组件有更新,调用模式有区别,或是2005环境要有的工程设置要做变更。 我查了许多资料,并仔细分享错误,其中有这么一个提示《而且符合所有其他 ComVisibility 需求》引起了我的注意,因为我发现Assemblyinfo.cs文件中有[assembly: ComVisible(false)]一行代码,于是我修改为[assembly: ComVisible(true)],编译运行测试结果。哈哈,终于看到我梦寐以求的如下界面了。

 

本来到这里我本以为大功告成了,结果后面的错误又让我焦头烂额了。

新问题:由于这个是测试的研究例子,我开始实际实施到我正在进行的项目中。结果运行又出现了新错误。我调试发现进行数据库链接的时候出现“已停用分散式交易管理員 (MSDTC) 的網路存取。請使用元件服務系統管理工具啟用 DTC,以使用 MSDTC 安全性設定中的網路存取”后来发现是本机的MSDTC服务的问题,我的是XP系统。设置步骤如下。
1)进入控制面板--系统管理工具--组件服务。点击我的电脑--属性--MSDTC--安全性设定,如下图


我一口气钩了许多我认为相关的选项,大家可以看到我上面的设置。

在后来的编译中我还发现的类似一些错误,我就不一一详细描述了,不过我把上面没有提到的错误的解决方案列举如下 :
1:  MSDTC on server 'ITEC-KS-CCNET' is unavailable. 为远端MSDTC没有启动,在组件服务中可以启动。
2:  Window2003下,MSDTC并没有缺省安装,还需要手工安装一下,方法是新增删除程序中,点击新增组件,然后选中Application Servers 点击详细资料,然后选中启用网络DTC存取,保存安装即可。当然安装后也要进入组件服务设置一下MSDTC的安全性设定。
3:  还有一个错误是您必須具備系統管理認證才能執行此工作。請連絡您的系統管理員以尋求協助。最后我发现是数据库服务器和运行此测试程序的机器根本不在一个网段,相互COM+组件无法互相访问,因为我用Telnet测试对方135,139端口根本不能通讯,因此需要开启此两个端口打开DCOM服务才可以。

我想经过上面的这写设置,你一定会看到你数据库单元测试的绿色通过条。
posted on 2008-04-21 10:36  海粟007  阅读(2893)  评论(3编辑  收藏  举报