欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

軟件測(cè)試培訓(xùn)之Web API數(shù)據(jù)驗(yàn)證與單元測(cè)試

2018-03-16 14:16:26 3226瀏覽

一、模型狀態(tài)-ModelState

我理解的ModelState是微軟在ASP.NETMVC中提出的一種新機(jī)制,它主要實(shí)現(xiàn)以下幾個(gè)功能:

1.保存客戶端傳過(guò)來(lái)的數(shù)據(jù),如果驗(yàn)證不通過(guò),把數(shù)據(jù)返回到客戶端,這樣可以保存用戶輸入,不需要重新輸入。

2.驗(yàn)證數(shù)據(jù),以及保存數(shù)據(jù)對(duì)應(yīng)的錯(cuò)誤信息。

3.微軟的一種DRY(Don'tRepeatYourself)設(shè)計(jì),通過(guò)ModelState可以做服務(wù)端驗(yàn)證,同時(shí)可以配合jqueryvalidation生成前端數(shù)據(jù)驗(yàn)證。

但是在WebAPI里面,ModelState的主要功能就只剩下第2點(diǎn)了。

需要注意的是,ModelState一般只做輸入驗(yàn)證,一些其他的業(yè)務(wù)驗(yàn)證還有要在特定的地方進(jìn)行處理。

二、數(shù)據(jù)注解-DataAnnotations

數(shù)據(jù)注解可以理解為驗(yàn)證數(shù)據(jù)的邏輯或方法,微軟本身有提供一批數(shù)據(jù)注解,當(dāng)然我們也可以自定義數(shù)據(jù)注解,以下是微軟提供的常見(jiàn)的數(shù)據(jù)注解:

1.Required-非空驗(yàn)證。

當(dāng)一個(gè)輸入是null時(shí)會(huì)引發(fā)一個(gè)驗(yàn)證錯(cuò)誤。

當(dāng)屬性類型是string的時(shí)候,如果設(shè)置了AllowEmptyStrings=false(默認(rèn)為false),那么輸入空字符串或者空格,也會(huì)引發(fā)一個(gè)驗(yàn)證錯(cuò)誤。

[Required]

publicstringName{get;set;}

[Required(AllowEmptyStrings=true)]

publicstringExchange{get;set;}

2.StringLength-長(zhǎng)度驗(yàn)證。

當(dāng)輸入大于指定最大長(zhǎng)度,或者小于最大指定長(zhǎng)度時(shí),會(huì)引發(fā)一個(gè)驗(yàn)證錯(cuò)誤。

[StringLength(100)]

publicstringSymbol{get;set;}

[StringLength(100,MinimumLength=10)]

publicstringName{get;set;}

3.RegularExpression-正則表達(dá)式驗(yàn)證。

當(dāng)輸入內(nèi)容不滿足指定的正則表達(dá)式時(shí),會(huì)引發(fā)一個(gè)驗(yàn)證錯(cuò)誤。

注:在.NETFramework4.6.1添加了一個(gè)MatchTimeoutInMilliseconds屬性,用來(lái)設(shè)定正則表達(dá)時(shí)驗(yàn)證時(shí)長(zhǎng)。如超時(shí),則拋出RegexMatchTimeoutException異常。

[RegularExpression("yourexpression")]

publicstringSymbol{get;set;}

4.Range-值范圍驗(yàn)證

當(dāng)輸入的值小于最小值或者大于最大值時(shí),會(huì)引發(fā)一個(gè)驗(yàn)證錯(cuò)誤,這里要求驗(yàn)證字段的類型需要實(shí)現(xiàn)IComparable接口。

[Range(10,100)]

publicdoubleOpenPrice{get;set;}

[Range(typeof(double),"10","100")]

publicdoubleClosePrice{get;set;}

5.Compare-對(duì)比驗(yàn)證

確保對(duì)象兩個(gè)屬性擁有相同的值。如果兩個(gè)值不同,會(huì)引發(fā)一個(gè)驗(yàn)證錯(cuò)誤。

publicstringName{get;set;}

[Compare("Name")]

publicstringConfirmName{get;set;}

6.Remote-遠(yuǎn)程調(diào)用驗(yàn)證

Remote可以利用服務(wù)端回調(diào)函數(shù)執(zhí)行客戶端的驗(yàn)證邏輯。

注:該數(shù)據(jù)注解是ASP.NETMVC特有的注解,在WebApi中無(wú)此注解。

[Remote("CheckName","Account"]

publicstringUserName{get;set;}

publicclassAccountController:Controller

{

publicJsonResultCheckName(stringname)

{

returnJson(true);

}

}

三、自定義數(shù)據(jù)注解

如果覺(jué)得微軟提供的數(shù)據(jù)注解不夠用,也可以自己寫數(shù)據(jù)注解,只需要繼承ValidationAttribute,并復(fù)寫IsValid方法。

下面是一個(gè)來(lái)自《ASP.NETMVC5高級(jí)編程》的一個(gè)例子MaxWordsAttribute,用于限制屬性的單詞個(gè)數(shù)。

publicclassMaxWordsAttribute:ValidationAttribute

{

privatereadonlyint_maxWords;

publicMaxWordsAttribute(intmaxWords)

{

_maxWords=maxWords;

}

protectedoverrideValidationResultIsValid(objectvalue,ValidationContextvalidationContext)

{

if(value!=null)

{

varvalueAsString=value.ToString();

if(valueAsString.Split('').Length>_maxWords)

{

returnnewValidationResult("Toomanywords!");

}

}

returnValidationResult.Success;

}

}

[Required]

[MaxWords(2)]

publicstringName{get;set;}

[HttpPost]

publicIHttpActionResultCreate(Stockstock)

{

if(!ModelState.IsValid)

{

returnBadRequest(ModelState);

}

returnCreatedAtRoute("Get",new{symbol=stock.Symbol},stock);

}

SwashbuckleHelpPage測(cè)試效果如下:

四、全局?jǐn)?shù)據(jù)驗(yàn)證

我們?cè)谑褂脭?shù)據(jù)驗(yàn)證的時(shí)候,往往會(huì)出現(xiàn)許多重復(fù)的代碼,如下圖:

有沒(méi)有辦法減少這些重復(fù)的代碼呢?我從“ModelValidationinASP.NETWebAPI”這篇文章中找到了方法。

首先,我們需要寫一個(gè)GlobalActionFilterAttribute。

publicclassGlobalActionFilterAttribute:ActionFilterAttribute

{

publicoverridevoidOnActionExecuting(HttpActionContextactionContext)

{

if(actionContext.ModelState.IsValid==false)

{

actionContext.Response=actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest,actionContext.ModelState);

}

}

}

然后,在WebApiConfig里注冊(cè)一下這個(gè)Attribute。

publicstaticvoidRegister(HttpConfigurationconfig)

{

config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute("DefaultApi","api/{controller}/{id}",new{id=RouteParameter.Optional});

//registerthecustomactionfilter

config.Filters.Add(newGlobalActionFilterAttribute());

}

那么,我們把Controller中的數(shù)據(jù)驗(yàn)證注釋掉,依舊會(huì)得到相同的效果。

如果想只對(duì)Post請(qǐng)求進(jìn)行驗(yàn)證,可以在GlobalActionFilterAttribute加對(duì)請(qǐng)求方式的判斷:

publicclassGlobalActionFilterAttribute:ActionFilterAttribute

{

publicoverridevoidOnActionExecuting(HttpActionContextactionContext)

{

//Ifyouonlywanttovalidatethepostrequest.

if(actionContext.Request.Method!=HttpMethod.Post)

{

return;

}

if(actionContext.ModelState.IsValid==false)

{

actionContext.Response=actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest,actionContext.ModelState);

}

}

}

如果某些Controller或Action需要繞過(guò)數(shù)據(jù)驗(yàn)證,那么可以這么實(shí)現(xiàn):

1.定義一個(gè)BypassModelStateValidationAttribute

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method,Inherited=false)]

publicsealedclassBypassModelStateValidationAttribute:Attribute

{

}

2.在不需要驗(yàn)證的Controller或者Action上加這個(gè)Attribute

[HttpPut]

[BypassModelStateValidation]

publicIHttpActionResultUpdate(Stockstock)

{

//if(!ModelState.IsValid)

//{

//returnBadRequest(ModelState);

//}

returnStatusCode(HttpStatusCode.NoContent);

}

3.在GlobalActionFilterAttribute加對(duì)BypassModelStateValidationAttribute的判斷:

publicclassGlobalActionFilterAttribute:ActionFilterAttribute

{

publicoverridevoidOnActionExecuting(HttpActionContextactionContext)

{

//Ifyouonlywanttovalidatethepostrequest.

if(actionContext.Request.Method!=HttpMethod.Post)

{

return;

}

varpassby=actionContext.ActionDescriptor.GetCustomAttributes<BypassModelStateValidationAttribute>().Any()||

actionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<BypassModelStateValidationAttribute>().Any();

if(passby)

{

return;

}

if(actionContext.ModelState.IsValid==false)

{

actionContext.Response=actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest,actionContext.ModelState);

}

}

}

五、單元測(cè)試

我使用BDD的風(fēng)格編寫單元測(cè)試,關(guān)于BDD的詳細(xì)信息,可查看我之前的文章《行為驅(qū)動(dòng)開(kāi)發(fā)(BDD)實(shí)踐示例》(http://www.cnblogs.com/Erik_Xu/p/5297981.html)。

對(duì)于全局?jǐn)?shù)據(jù)驗(yàn)證,我設(shè)計(jì)了3個(gè)測(cè)試用例。

1.非Post請(qǐng)求不做驗(yàn)證-HttpMethodNotMatched

feature描述:

測(cè)試代碼:

[Binding]

[Scope(Scenario=@"HttpMethodNotMatched")]

publicclassHttpMethodNotMatchedTest:GlobalActionFilterAttributeTests

{

[Given(@"非Post方式的請(qǐng)求")]

publicvoidGiven()

{

HttpActionContext.Request.Method=HttpMethod.Get;

}

[When(@"執(zhí)行OnActionExecuting方法")]

publicvoidWhen()

{

GlobalActionFilterAttribute.OnActionExecuting(HttpActionContext);

}

[Then(@"Response為空")]

publicvoidThen()

{

Assert.IsNull(HttpActionContext.Response);

}

}

2.設(shè)置了跳過(guò)驗(yàn)證-BypassModelStateValidation

feature描述:

測(cè)試代碼:

[Binding]

[Scope(Scenario=@"BypassModelStateValidation")]

publicclassBypassModelStateValidationTest:GlobalActionFilterAttributeTests

{

[Given(@"BypassModelStateValidationAttribute")]

publicvoidGiven()

{

HttpActionContext.Request.Method=HttpMethod.Post;

HttpActionContext.ActionDescriptor=ActionDescriptorMock.Object;

ActionDescriptorMock.Setup(m=>m.GetCustomAttributes<BypassModelStateValidationAttribute>()).Returns(newCollection<BypassModelStateValidationAttribute>(new[]{newBypassModelStateValidationAttribute()}));

HttpActionContext.ControllerContext.ControllerDescriptor=ControllerDescriptorMock.Object;

ControllerDescriptorMock.Setup(m=>m.GetCustomAttributes<BypassModelStateValidationAttribute>()).Returns(newCollection<BypassModelStateValidationAttribute>());

}

[When(@"執(zhí)行OnActionExecuting方法")]

publicvoidWhen()

{

GlobalActionFilterAttribute.OnActionExecuting(HttpActionContext);

}

[Then(@"Response為空")]

publicvoidThen()

{

Assert.IsNull(HttpActionContext.Response);

}

}

3.驗(yàn)證不通過(guò)-ModelStateInvalid

feature描述:

測(cè)試代碼:

[Binding]

[Scope(Scenario=@"ModelStateInvalid")]

publicclassModelStateInvalidTest:GlobalActionFilterAttributeTests

{

[Given(@"ModelState錯(cuò)誤信息")]

publicvoidGiven()

{

HttpActionContext.Request.Method=HttpMethod.Post;

HttpActionContext.ActionDescriptor=ActionDescriptorMock.Object;

ActionDescriptorMock.Setup(m=>m.GetCustomAttributes<BypassModelStateValidationAttribute>()).Returns(newCollection<BypassModelStateValidationAttribute>());

HttpActionContext.ControllerContext.ControllerDescriptor=ControllerDescriptorMock.Object;

ControllerDescriptorMock.Setup(m=>m.GetCustomAttributes<BypassModelStateValidationAttribute>()).Returns(newCollection<BypassModelStateValidationAttribute>());

HttpActionContext.ModelState.AddModelError("stock.Name","TheNamefieldisrequired.");

}

[When(@"執(zhí)行OnActionExecuting方法")]

publicvoidWhen()

{

GlobalActionFilterAttribute.OnActionExecuting(HttpActionContext);

}

[Then(@"返回BadRequest")]

publicvoidThen()

{

Assert.AreEqual(HttpStatusCode.BadRequest,HttpActionContext.Response.StatusCode);

}

}

單元測(cè)試結(jié)果:

說(shuō)明:

GlobalActionFilterAttributeTests是單元測(cè)試的父類,公共的部分可以抽取到這里。其中ContextUtil是微軟源碼中的測(cè)試輔助類。

publicclassGlobalActionFilterAttributeTests

{

protectedreadonlyMock<HttpActionDescriptor>ActionDescriptorMock=newMock<HttpActionDescriptor>();

protectedreadonlyMock<HttpControllerDescriptor>ControllerDescriptorMock=newMock<HttpControllerDescriptor>();

protectedHttpActionContextHttpActionContext;

protectedGlobalActionFilterAttributeGlobalActionFilterAttribute;

publicGlobalActionFilterAttributeTests()

{

HttpActionContext=ContextUtil.CreateActionContext();

GlobalActionFilterAttribute=newGlobalActionFilterAttribute();

}

}

以上就是關(guān)于軟件測(cè)試培訓(xùn)之Web API數(shù)據(jù)驗(yàn)證與單元測(cè)試的詳細(xì)介紹,最后想要了解更多關(guān)于軟件測(cè)試培訓(xùn)發(fā)展前景趨勢(shì),請(qǐng)關(guān)注扣丁學(xué)堂官網(wǎng)、微信等平臺(tái),扣丁學(xué)堂IT職業(yè)在線學(xué)習(xí)教育平臺(tái)為您提供權(quán)威的軟件測(cè)試視頻教程系統(tǒng),通過(guò)千鋒扣丁學(xué)堂金牌講師在線錄制的軟件測(cè)試在線視頻教程,讓你快速掌握軟件測(cè)試從入門到精通開(kāi)發(fā)實(shí)戰(zhàn)技能。


扣丁學(xué)堂微信公眾號(hào)



【關(guān)注微信公眾號(hào)獲取更多學(xué)習(xí)資料】



查看更多關(guān)于“軟件測(cè)試技術(shù)資訊”的相關(guān)文章>>

標(biāo)簽: 軟件測(cè)試培訓(xùn) 軟件測(cè)試工程師 軟件測(cè)試在線視頻 軟件測(cè)試視頻教程 軟件測(cè)試教程 白盒測(cè)試 黑盒測(cè)試

熱門專區(qū)

暫無(wú)熱門資訊

課程推薦

微信
微博
15311698296

全國(guó)免費(fèi)咨詢熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權(quán)所有   北京市海淀區(qū)寶盛北里西區(qū)28號(hào)中關(guān)村智誠(chéng)科創(chuàng)大廈4層
京ICP備2021002079號(hào)-2   Copyright ? 2017 - 2022
返回頂部 返回頂部