55
66### Table of contents
77
8- - Action call configuration
8+ - Initial configuration
99 - [ Controller instantiation] ( #controller-instantiation )
1010 - [ HTTP request message] (#http-request-message)
1111 - [ Authenticated user] ( #authenticated-user )
1212 - [ Calling actions] ( #calling-actions )
13+ - Controller validations
14+ - [ Controller attributes testing] ( #controller-attributes-testing )
1315 - Action call validations
16+ - [ Action attributes testing] ( #action-attributes-testing )
1417 - [ Model state validation] ( #model-state-validation )
1518 - [ Catching thrown exceptions] ( #catching-thrown-exceptions )
1619 - Action result validations
@@ -248,6 +251,309 @@ MyWebApi
248251 .Controller <WebApiController >()
249252 .CallingAsync (c => c .SomeActionAsync ());
250253```
254+ [ To top] ( #table-of-contents )
255+
256+ ### Controller attributes testing
257+
258+ You can test for specific or custom controller attributes:
259+
260+ ``` c#
261+ // tests whether controller has no attributes
262+ MyWebApi
263+ .Controller <WebApiController >()
264+ .ShouldHave ()
265+ .NoAttributes ();
266+
267+ // tests whether controller has at least 1 attribute of any type
268+ MyWebApi
269+ .Controller <WebApiController >()
270+ .ShouldHave ()
271+ .Attributes ();
272+
273+ // tests whether controller has specific number of attributes
274+ MyWebApi
275+ .Controller <WebApiController >()
276+ .ShouldHave ()
277+ .Attributes (withTotalNumberOf : 2 );
278+
279+ // tests whether controller has specific attribute type
280+ MyWebApi
281+ .Controller <WebApiController >()
282+ .ShouldHave ()
283+ .Attributes (attributes => attributes
284+ .ContainingAttributeOfType <AuthorizeAttribute >());
285+
286+ // tests whether controller has RouteAttribute
287+ // with specific expected route template
288+ MyWebApi
289+ .Controller <WebApiController >()
290+ .ShouldHave ()
291+ .Attributes (attributes => attributes
292+ .ChangingRouteTo (" /api/anotheraction" ));
293+
294+ // tests whether controller has RouteAttribute
295+ // with specific expected route template
296+ // and optional expected name and order
297+ MyWebApi
298+ .Controller <WebApiController >()
299+ .ShouldHave ()
300+ .Attributes (attributes => attributes
301+ .ChangingRouteTo (
302+ " /api/anotheraction" ,
303+ withName : " SomeRoute" ,
304+ withOrder : 1 ));
305+
306+ // tests whether controller has RoutePrefixAttribute
307+ // with specific expected route prefix
308+ MyWebApi
309+ .Controller <WebApiController >()
310+ .ShouldHave ()
311+ .Attributes (attributes => attributes
312+ .ChangingRoutePrefixTo (" /api/anothercontroller" ));
313+
314+ // tests whether controller has AllowAnonymousAttribute
315+ MyWebApi
316+ .Controller <WebApiController >()
317+ .ShouldHave ()
318+ .Attributes (attributes => attributes
319+ .AllowingAnonymousRequests ());
320+
321+ // tests whether controller has AuthorizeAttribute
322+ MyWebApi
323+ .Controller <WebApiController >()
324+ .ShouldHave ()
325+ .Attributes (attributes => attributes
326+ .RestrictingForAuthorizedRequests ());
327+
328+ // tests whether controller has AuthorizeAttribute
329+ // with expected authorized roles
330+ // and/or expected authorized users
331+ MyWebApi
332+ .Controller <WebApiController >()
333+ .ShouldHave ()
334+ .Attributes (attributes => attributes
335+ .RestrictingForAuthorizedRequests (
336+ withAllowedRoles : " Admin,Moderator" ,
337+ withAllowedUsers : " John,George" ));
338+
339+ // combining tests with AndAlso
340+ MyWebApi
341+ .Controller <WebApiController >()
342+ .ShouldHave ()
343+ .Attributes (attributes =>
344+ attributes
345+ .AllowingAnonymousRequests ()
346+ .AndAlso () // AndAlso is not necessary
347+ .ChangingRoutePrefixTo (" /api/anothercontroller" ));
348+ ```
349+
350+ [ To top] ( #table-of-contents )
351+
352+ ### Action attributes testing
353+
354+ You can test for specific or custom action attributes decorated on the called action:
355+
356+ ``` c#
357+ // tests whether action has no attributes
358+ MyWebApi
359+ .Controller <WebApiController >()
360+ .Calling (c => c .SomeAction ())
361+ .ShouldHave ()
362+ .NoActionAttributes ();
363+
364+ // tests whether action has at least 1 attribute of any type
365+ MyWebApi
366+ .Controller <WebApiController >()
367+ .Calling (c => c .SomeAction ())
368+ .ShouldHave ()
369+ .ActionAttributes ();
370+
371+ // tests whether action has specific number of attributes
372+ MyWebApi
373+ .Controller <WebApiController >()
374+ .Calling (c => c .SomeAction ())
375+ .ShouldHave ()
376+ .ActionAttributes (withTotalNumberOf : 2 );
377+
378+ // tests whether action has specific attribute type
379+ MyWebApi
380+ .Controller <WebApiController >()
381+ .Calling (c => c .SomeAction ())
382+ .ShouldHave ()
383+ .ActionAttributes (attributes => attributes
384+ .ContainingAttributeOfType <HttpGetAttribute >());
385+
386+ // tests whether action has ActionNameAttribute
387+ // with specific expected name
388+ MyWebApi
389+ .Controller <WebApiController >()
390+ .Calling (c => c .SomeAction ())
391+ .ShouldHave ()
392+ .ActionAttributes (attributes => attributes
393+ .ChangingActionNameTo (" AnotherAction" ));
394+
395+ // tests whether action has RouteAttribute
396+ // with specific expected route template
397+ MyWebApi
398+ .Controller <WebApiController >()
399+ .Calling (c => c .SomeAction ())
400+ .ShouldHave ()
401+ .ActionAttributes (attributes => attributes
402+ .ChangingRouteTo (" /api/anotheraction" ));
403+
404+ // tests whether action has RouteAttribute
405+ // with specific expected route template
406+ // and optional expected name and order
407+ MyWebApi
408+ .Controller <WebApiController >()
409+ .Calling (c => c .SomeAction ())
410+ .ShouldHave ()
411+ .ActionAttributes (attributes => attributes
412+ .ChangingRouteTo (
413+ " /api/anotheraction" ,
414+ withName : " SomeRoute" ,
415+ withOrder : 1 ));
416+
417+ // tests whether action has AllowAnonymousAttribute
418+ MyWebApi
419+ .Controller <WebApiController >()
420+ .Calling (c => c .SomeAction ())
421+ .ShouldHave ()
422+ .ActionAttributes (attributes => attributes
423+ .AllowingAnonymousRequests ());
424+
425+ // tests whether action has AuthorizeAttribute
426+ MyWebApi
427+ .Controller <WebApiController >()
428+ .Calling (c => c .SomeAction ())
429+ .ShouldHave ()
430+ .ActionAttributes (attributes => attributes
431+ .RestrictingForAuthorizedRequests ());
432+
433+ // tests whether action has AuthorizeAttribute
434+ // with expected authorized roles
435+ // and/or expected authorized users
436+ MyWebApi
437+ .Controller <WebApiController >()
438+ .Calling (c => c .SomeAction ())
439+ .ShouldHave ()
440+ .ActionAttributes (attributes => attributes
441+ .RestrictingForAuthorizedRequests (
442+ withAllowedRoles : " Admin,Moderator" ,
443+ withAllowedUsers : " John,George" ));
444+
445+ // tests whether action has NonActionAttribute
446+ MyWebApi
447+ .Controller <WebApiController >()
448+ .Calling (c => c .SomeAction ())
449+ .ShouldHave ()
450+ .ActionAttributes (attributes => attributes
451+ .DisablingActionCall ());
452+
453+ // tests whether action has restriction for HTTP method
454+ // by providing type of the attribute
455+ // * tests for AcceptsVerbsAttribute or the specific HttpGetAttribute, HttpPostAttribute, etc.
456+ MyWebApi
457+ .Controller <WebApiController >()
458+ .Calling (c => c .SomeAction ())
459+ .ShouldHave ()
460+ .ActionAttributes (attributes => attributes
461+ .RestrictingForRequestsWithMethod <HttpGetAttribute >());
462+
463+ // tests whether action has restriction for HTTP method
464+ // by providing the expected method as string
465+ // *tests for AcceptsVerbsAttribute or the specific HttpGetAttribute, HttpPostAttribute, etc.
466+ MyWebApi
467+ .Controller <WebApiController >()
468+ .Calling (c => c .SomeAction ())
469+ .ShouldHave ()
470+ .ActionAttributes (attributes => attributes
471+ .RestrictingForRequestsWithMethod (" GET" ));
472+
473+ // tests whether action has restriction for HTTP method
474+ // by providing the expected method as HttpMethod class
475+ // *tests for AcceptsVerbsAttribute or the specific HttpGetAttribute, HttpPostAttribute, etc.
476+ MyWebApi
477+ .Controller <WebApiController >()
478+ .Calling (c => c .SomeAction ())
479+ .ShouldHave ()
480+ .ActionAttributes (attributes => attributes
481+ .RestrictingForRequestsWithMethod (HttpMethod .Get ));
482+
483+ // tests whether action has restriction for HTTP methods
484+ // by providing IEnumerable of strings
485+ // *tests for AcceptsVerbsAttribute or the specific HttpGetAttribute, HttpPostAttribute, etc.
486+ MyWebApi
487+ .Controller <WebApiController >()
488+ .Calling (c => c .SomeAction ())
489+ .ShouldHave ()
490+ .ActionAttributes (attributes => attributes
491+ .RestrictingForRequestsWithMethod (new List <string > { " GET" , " HEAD" }));
492+
493+ // tests whether action has restriction for HTTP methods
494+ // by providing strings parameters
495+ // *tests for AcceptsVerbsAttribute or the specific HttpGetAttribute, HttpPostAttribute, etc.
496+ MyWebApi
497+ .Controller <WebApiController >()
498+ .Calling (c => c .SomeAction ())
499+ .ShouldHave ()
500+ .ActionAttributes (attributes => attributes
501+ .RestrictingForRequestsWithMethod (" GET" , " HEAD" ));
502+
503+ // tests whether action has restriction for HTTP methods
504+ // by providing IEnumerable of HttpMethod class
505+ // *tests for AcceptsVerbsAttribute or the specific HttpGetAttribute, HttpPostAttribute, etc.
506+ MyWebApi
507+ .Controller <WebApiController >()
508+ .Calling (c => c .SomeAction ())
509+ .ShouldHave ()
510+ .ActionAttributes (attributes => attributes
511+ .RestrictingForRequestsWithMethod (new List <HttpMethod >
512+ {
513+ HttpMethod .Get ,
514+ HttpMethod .Head
515+ }));
516+
517+ // tests whether action has restriction for HTTP methods
518+ // by providing HttpMethod parameters
519+ // *tests for AcceptsVerbsAttribute or the specific HttpGetAttribute, HttpPostAttribute, etc.
520+ MyWebApi
521+ .Controller <WebApiController >()
522+ .Calling (c => c .SomeAction ())
523+ .ShouldHave ()
524+ .ActionAttributes (attributes => attributes
525+ .RestrictingForRequestsWithMethod (HttpMethod .Get , HttpMethod .Head ));
526+
527+ // combining tests with AndAlso
528+ MyWebApi
529+ .Controller <WebApiController >()
530+ .Calling (c => c .SomeAction ())
531+ .ShouldHave ()
532+ .ActionAttributes (attributes =>
533+ attributes
534+ .AllowingAnonymousRequests ()
535+ .AndAlso () // AndAlso is not necessary
536+ .DisablingActionCall ()
537+ .AndAlso ()
538+ .RestrictingForRequestsWithMethod <HttpGetAttribute >());
539+
540+ // continuing testing other aspects of the action
541+ MyWebApi
542+ .Controller <WebApiController >()
543+ .Calling (c => c .VariousAttributesAction ())
544+ .ShouldHave ()
545+ .ActionAttributes (attributes =>
546+ attributes
547+ .AllowingAnonymousRequests ()
548+ .AndAlso ()
549+ .DisablingActionCall ())
550+ .AndAlso ()
551+ .ShouldHave ()
552+ .ValidModelState ()
553+ .AndAlso ()
554+ .ShouldReturn ()
555+ .Ok ();
556+ ```
251557
252558[ To top] ( #table-of-contents )
253559
@@ -1641,6 +1947,15 @@ var controller = MyWebApi
16411947 .Ok ()
16421948 .AndProvideTheController ();
16431949
1950+ // get controller attributes
1951+ // * currently method returns correct attributes
1952+ // * only after ShouldHave().Attributes() call
1953+ var attributes = MyWebApi
1954+ .Controller <WebApiController >()
1955+ .ShouldHave ()
1956+ .Attributes ()
1957+ .AndProvideTheControllerAttributes ();
1958+
16441959// get the HTTP request message
16451960// * method is available almost everywhere throughout the API
16461961var controller = MyWebApi
@@ -1658,6 +1973,16 @@ var actionName = MyWebApi
16581973 .ShouldReturn ()
16591974 .Ok ()
16601975 .AndProvideTheActionName ();
1976+
1977+ // get action attributes
1978+ // * currently method returns correct attributes
1979+ // * only after ShouldHave().ActionAttributes() call
1980+ var attributes = MyWebApi
1981+ .Controller <WebApiController >()
1982+ .Calling (c => c .SomeAction ())
1983+ .ShouldHave ()
1984+ .ActionAttributes ()
1985+ .AndProvideTheActionAttributes ();
16611986
16621987// get the action result
16631988// * method is available on most methods which assert the action result
0 commit comments