日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

WF单元测试系列3:测试Activity的行为

發布時間:2025/7/14 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WF单元测试系列3:测试Activity的行为 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?????上一篇中介紹了如何簡單地測試Activity的行為,我們只是使用VSTS的單元測試工具,捕獲了一個期待的異常,這樣簡單的行為測試當然是不能滿足我們的需求的,我們要進一步測試Activity的更多,更復雜的行為。
?????比如我們有一個LogActivity 負責寫日志,任何調用它的結果等同于調用一個ILog接口的一個Write()方法。我們就要寫一個單元測試,測試是否LogActivity的調用等同于對ILog接口的Write()方法的調用。
?????有的人不禁要問了,這樣的測試如何做呢?我們的測試工具只支持Assert操作,難道我要去Check日志文件,看看兩個日志是否相等嗎?答案是否定的,我們不會這么做,因為這樣還屬于“狀態測試”的范疇,而不是“行為測試”。
?????還好有人想到了這一點,提供給我們現成的工具,這就是Mock Object Framework。Mock Object Framework基于單元測試中的這樣幾個問題:
?????1.在一個龐大的系統中,成百上千個類共同協調完成一個功能。往往一個調用的背后,是幾十個類在共同工作,而且很多類的創建很耗費資源和時間。在這樣的情況下,運行一個測試的代價可想而知,何況我們每次對代碼做一次改動,就要運行單元測試呢。

?????2.很多代碼都需要調用外部資源,比如,讀取配置文件,讀取數據庫,調用遠程的Web Service等等。這樣的操作很費時間,最主要的是依賴外部的資源。如果外部資源處了問題,測試將無法進行下去。

?????3.對系統的行為無法準確捕獲。一個簡單的調用,系統究竟調用了那些類的那個方法,調用了幾次,做了幾次查詢,修改,等等,一系列的操作都無法準確測試,難以保證單元測試的嚴謹性。

?????基于以上幾點考慮(當然不是全部的),Mock Object Framework出現了。它解決了這些問題,

?????所以成為了TDD的必備武器!

?????Mock Object Framework的主要功能:

?????1.Mock Object---顧名思義,就是模仿對象。正是由于單元測試中龐大的對象群的創建太耗費資源和時間,所以我們使用Mock Object來代替那些對象。Mock Object是輕量級的,代價很低,所以大大減少單元測試的開銷。

?????2.對于一些需要訪問外部資源的對象,Mock可以用硬編碼代替對外部資源的訪問。從而提高效率。

?????3.Mock Object Framework可以準確地記錄所模仿的對象的一切操作,使得我們可以準確地測試對象的行為是否符合要求。

?????4.Mock Object Framework可以模仿接口,抽象類,或者尚未實現的類,從而加快開發速度。

?????關于Mock Object Framework,大家可以去找一些資料。
?????這里我們使用的是Rhino Mock,大家可以去這里看Rhino Mock的簡單介紹:http://stephenwalther.com/blog/archive/2008/03/23/tdd-introduction-to-rhino-mocks.aspx
?????下面開始我們的單元測試:
?????在前文的工程中,加入一個名叫的Activity,繼承自BaseEmployeeActivity。定義三個屬性:

StoreNewAcmeEmployee
????????public?static?readonly?DependencyProperty
????????????????NewEmployeeProperty?
=?DependencyProperty.Register("NewEmployee",
????????????????????
typeof(AcmeEmployee),?typeof(StoreNewAcmeEmployee));

????????
public?AcmeEmployee?NewEmployee
????????
{
????????????
get?{?return?(AcmeEmployee)GetValue(NewEmployeeProperty);?}
????????????
set?{?SetValue(NewEmployeeProperty,?value);?}
????????}


????????
public?IEmployeeRepository?EmployeeDataStore?{?get;?set;?}

????????
protected?override?ActivityExecutionStatus?Execute(ActivityExecutionContext?

executionContext)
????????
{

????????????
return?ActivityExecutionStatus.Closed;
????????}


?????我們設定這個Activity的功能是:根據給定的參數,創建一個NewEmployee對象,把它存儲在EmployeeDataStore對象中。我們先不實現Execute()方法。注意:EmployeeDataStore會在后面使用依賴注入賦值。
?????為了測試這個Activity,我們如法炮制,在測試工程中加一個新的Activity:StoreNewAcmeEmployee_Accessor,繼承自StoreNewAcmeEmployee。并Wrap它的Execute方法。
?????接下來添加一個測試類:StoreNewAcmeEmployee_ActivityShould。記得引用Rhino.Mocks庫。
?????先把代碼貼出來:

StoreNewAcmeEmployee_ActivityShould
using?System;
using?AcmeCorp.DomainLibrary.AcmeEmployeeDomain;
using?Microsoft.VisualStudio.TestTools.UnitTesting;
using?NewEmployeeWFLibrary.Activities;
using?NewEmployeeWFLibrary_Test.Helpers;
using?Rhino.Mocks;//引用Rhino?Mock庫

namespace?NewEmployeeWFLibrary_Test.Activities
{
????[TestClass]
????
public?class?StoreNewAcmeEmployee_ActivityShould
????
{
????????
//被Mock的對象,將被注入到StoreNewAcmeEmployee的EmployeeDataStore屬性。
????????private?IEmployeeRepository?_mockEmployeeRepository;
????????
????????
//Mock功能類
????????private?MockRepository?_mocker;

????????[TestInitialize]
????????
public?void?TestInitializer()
????????
{
????????????
//初始化Mock功能類???????????
????????????_mocker?=?new?MockRepository();

????????????
//創建Mock對象
????????????_mockEmployeeRepository?=?_mocker.CreateMock<IEmployeeRepository>();
????????}


????????[TestMethod]
????????
public?void?CallAddOnTheRepo()
????????
{
????????????
//記錄Mock對象的操作
????????????using?(_mocker.Record())
????????????
{
????????????????_mockEmployeeRepository.Add(
null);
????????????????LastCall.IgnoreArguments();
//忽略上面的null參數,即傳什么參數都一樣


????????????}


????????????
//回放Mock對象的操作,Rhino?Mock會自動檢驗對被Mock的對

象_mockEmployeeRepository的操作與上面記錄的是否一致
????????????
//如果不一致,就會自動拋出異常
????????????using?(_mocker.Playback())
????????????
{
????????????????
using?(StoreNewAcmeEmployee_Accessor?activity?=?new?

StoreNewAcmeEmployee_Accessor())
????????????????
{
????????????????????SetActivityProperties(activity,?Mother.FIRST_NAME,?

Mother.LAST_NAME,?Mother.EMAIL,
??????????????????????????????????????????_mockEmployeeRepository);
????????????????????activity.Execute_Accessor(
null);
????????????????}

????????????}

????????}

????????

????????
private?void?SetActivityProperties(StoreNewAcmeEmployee?activity,?string?

firstName,?
string?lastName,
???????????????????????????????????????????
string?email,?IEmployeeRepository?

employeeRepo)
????????
{
????????????activity.FirstName?
=?firstName;
????????????activity.LastName?
=?lastName;
????????????activity.Email?
=?email;
????????????activity.EmployeeDataStore?
=?employeeRepo;//注入被Mock對象
????????}

????}

}


?

?????在上面的代碼中,下面一句比較重要
?????_mockEmployeeRepository = _mocker.CreateMock<IEmployeeRepository>();
?????這一句創建了針對接口IEmployeeRepository的Mock對象。注意:在我的工程里,名沒有實現這個接口。這就是Mock的特點,可以不用實現功能就能測試。可謂針對接口測試吧!:)
?????在接下來的測試方法中,首先使用_mocker.Record()記錄對Mock對象的操作。在_mocker.Record()的Unsing塊中的所有操作,都是我們期待的Mock對象的“行為”。而_mocker.Playback()塊則是對Activity的實際測試過程,在這個過程中,必須和Record塊對_mockEmployeeRepository的操作一致------也就是說,也調用了它的Add()方法。如果一致,測試通過,否則Rhino Mock會拋出異常,測試失敗!
?????我們運行一下測試,失敗!因為還沒有為StoreNewAcmeEmployee的Execute()方法添加邏輯。

?????回過頭來實現StoreNewAcmeEmployee的Execute()方法:

Execute
protected?override?ActivityExecutionStatus?Execute(ActivityExecutionContext?

executionContext)
????????{
????????????NewEmployee?
=?new?AcmeEmployee(Guid.NewGuid().ToString(),?FirstName,?

LastName,?Email);
????????????EmployeeDataStore.Add(NewEmployee);
????????????
return?ActivityExecutionStatus.Closed;
????????}

???????

?????最關鍵的一個操作就是調用了注入進來的EmployeeDataStore的Add()方法!
?????再次運行測試!通過!
?????上面討論了如何對Activity進行“行為測試”,當然這還只是一個開始。
?????類似前一篇中提到的,我們為測試加入“異常處理”。
?????添加如下測試方法和輔助方法:

ThrowExceptionOnNullFirstName
[TestMethod]
????????[ExpectedException(
typeof(ArgumentNullException))]
????????
public?void?ThrowExceptionOnNullFirstName()
????????
{
????????????ExerciseActivityWithNoExpectations(
null,?Mother.LAST_NAME,?

Mother.EMAIL,?_mockEmployeeRepository);
????????}


????????
private?void?ExerciseActivityWithNoExpectations(string?firstName,?string?

lastName,?
string?email,
????????????????????????????????????????????????????????IEmployeeRepository?

employeeRepository)
????????
{
????????????_mocker.Record().Dispose();
//不記錄任何操作

????????????
using?(_mocker.Playback())
????????????
{
????????????????
using?(StoreNewAcmeEmployee_Accessor?activity?=?new?

StoreNewAcmeEmployee_Accessor())
????????????????
{
????????????????????SetActivityProperties(activity,?firstName,?lastName,?email,?

employeeRepository);

????????????????????activity.Execute_Accessor(
null);
????????????????}

????????????}

????????}


???????

?????在這里,沒有對Mock對象進行任何記錄。就是說不期待對Mock對象進行任何操作。但是期待一個異常:ArgumentNullException,因為傳入和一個Null參數。

?????回到StoreNewAcmeEmployee中,改造Execute()方法為:
?

Execute
???protected?override?ActivityExecutionStatus
????????????????Execute(ActivityExecutionContext?executionContext)
????????
{
????????????EnsurePropertiesAreValid();
????????????
????????????NewEmployee?
=?new?AcmeEmployee(Guid.NewGuid().ToString(),
??????????????????????????????FirstName,
??????????????????????????????LastName,
??????????????????????????????Email);

????????????EmployeeDataStore.Add(NewEmployee);

????????????
return?ActivityExecutionStatus.Closed;
????????}


????????
private?void?EnsurePropertiesAreValid()
????????
{
????????????
if?(Email?==?null)
????????????????
throw?new?ArgumentNullException("Email");

????????????
if?(FirstName?==?null)
????????????????
throw?new?ArgumentNullException("FirstName");

????????????
if?(LastName?==?null)
????????????????
throw?new?ArgumentNullException("LastName");

????????????
if?(EmployeeDataStore?==?null)
????????????????
throw?new?ArgumentNullException("Email");
????????}


?????在調用EmployeeDataStore的Add()方法之前,檢查參數是否合法,不合法就拋出異常,不調用EmployeeDataStore的Add()方法。
?????運行測試,通過!
?????對Activity的行為測試就到這里,下次為大家介紹對Workflow的測試。
?????附源碼:NewEmployeeWF3.rar

?????注:以上示例來自WF3.5 Hands On Lab,英文好的朋友可以去這里看:https://www.microsoft.com/resources/virtuallabs/step3-msdn.aspx?LabId=c4a993a5-d498-4d5c-9f98-476c1f496d15&BToken=reg

轉載于:https://www.cnblogs.com/zhaojunqi/archive/2009/03/10/1407951.html

總結

以上是生活随笔為你收集整理的WF单元测试系列3:测试Activity的行为的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。