Skip to content

Commit bed3521

Browse files
authored
Merge pull request #333 - Added ServiceFilterAttributeBuilder and TypeFilterAttributeBuilder
Added ServiceFilterAttributeBuilder and TypeFilterAttributeBuilder
2 parents 0b0a77a + 60e6418 commit bed3521

File tree

21 files changed

+1270
-18
lines changed

21 files changed

+1270
-18
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Attributes
2+
{
3+
using System;
4+
using Internal.TestContexts;
5+
using Utilities;
6+
7+
public abstract class BaseAttributeTestBuilderWithOrderAndType<TAttribute> : BaseAttributeTestBuilderWithOrder<TAttribute>
8+
where TAttribute : Attribute
9+
{
10+
/// <summary>
11+
/// Initializes a new instance of the <see cref="BaseAttributeTestBuilderWithOrderAndType{TAttribute}"/> class.
12+
/// </summary>
13+
/// <param name="testContext"><see cref="ComponentTestContext"/> containing data about the currently executed assertion chain.</param>
14+
/// <param name="attributeName">Attribute name to use in case of failed validation.</param>
15+
/// <param name="failedValidationAction">Action to call in case of failed validation.</param>
16+
protected BaseAttributeTestBuilderWithOrderAndType(
17+
ComponentTestContext testContext,
18+
string attributeName,
19+
Action<string, string> failedValidationAction)
20+
: base(testContext, attributeName, failedValidationAction)
21+
{
22+
}
23+
24+
protected virtual void ValidateType(Type type, Func<TAttribute, Type> getTypeValueFunc)
25+
{
26+
this.Attribute = (TAttribute)Activator.CreateInstance(typeof(TAttribute), type);
27+
this.Validations.Add((expected, actual) =>
28+
{
29+
var expectedType = getTypeValueFunc(expected);
30+
var actualType = getTypeValueFunc(actual);
31+
32+
if (Reflection.AreDifferentTypes(expectedType, actualType))
33+
{
34+
this.FailedValidationAction(
35+
$"{this.ExceptionMessagePrefix}'{expectedType.ToFriendlyTypeName()}' type",
36+
$"in fact found '{actualType.ToFriendlyTypeName()}'");
37+
}
38+
});
39+
}
40+
}
41+
}

src/MyTested.AspNetCore.Mvc.Controllers.Attributes/Builders/Attributes/MiddlewareFilterAttributeTestBuilder.cs

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
/// <summary>
1010
/// Used for testing <see cref="MiddlewareFilterAttribute"/>.
1111
/// </summary>
12-
public class MiddlewareFilterAttributeTestBuilder : BaseAttributeTestBuilderWithOrder<MiddlewareFilterAttribute>,
12+
public class MiddlewareFilterAttributeTestBuilder : BaseAttributeTestBuilderWithOrderAndType<MiddlewareFilterAttribute>,
1313
IAndMiddlewareFilterAttributeTestBuilder
1414
{
1515
/// <summary>
@@ -26,20 +26,7 @@ public MiddlewareFilterAttributeTestBuilder(
2626
/// <inheritdoc />
2727
public IAndMiddlewareFilterAttributeTestBuilder OfType(Type configurationType)
2828
{
29-
this.Attribute = new MiddlewareFilterAttribute(configurationType);
30-
this.Validations.Add((expected, actual) =>
31-
{
32-
var expectedType = expected.ConfigurationType;
33-
var actualType = actual.ConfigurationType;
34-
35-
if (Reflection.AreDifferentTypes(expectedType, actualType))
36-
{
37-
this.FailedValidationAction(
38-
$"{this.ExceptionMessagePrefix}'{expectedType.ToFriendlyTypeName()}' type",
39-
$"in fact found '{actualType.ToFriendlyTypeName()}'");
40-
}
41-
});
42-
29+
this.ValidateType(configurationType, attr => attr.ConfigurationType);
4330
return this;
4431
}
4532

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Attributes
2+
{
3+
using System;
4+
using Microsoft.AspNetCore.Mvc;
5+
using Contracts.Attributes;
6+
using Internal.TestContexts;
7+
8+
/// <summary>
9+
/// Used for testing <see cref="ServiceFilterAttribute"/>.
10+
/// </summary>
11+
public class ServiceFilterAttributeTestBuilder : BaseAttributeTestBuilderWithOrderAndType<ServiceFilterAttribute>,
12+
IAndServiceFilterAttributeTestBuilder
13+
{
14+
/// <summary>
15+
/// Initializes a new instance of the <see cref="ServiceFilterAttributeTestBuilder"/> class.
16+
/// </summary>
17+
/// <param name="testContext"><see cref="ComponentTestContext"/> containing data about the currently executed assertion chain.</param>
18+
/// <param name="failedValidationAction">Action to call in case of failed validation.</param>
19+
public ServiceFilterAttributeTestBuilder(
20+
ComponentTestContext testContext,
21+
Action<string, string> failedValidationAction)
22+
: base(testContext, nameof(ServiceFilterAttribute), failedValidationAction)
23+
=> this.Attribute = new ServiceFilterAttribute(typeof(object));
24+
25+
/// <inheritdoc />
26+
public IAndServiceFilterAttributeTestBuilder OfType(Type type)
27+
{
28+
this.ValidateType(type, attr => attr.ServiceType);
29+
return this;
30+
}
31+
32+
/// <inheritdoc />
33+
public IAndServiceFilterAttributeTestBuilder WithOrder(int order)
34+
{
35+
this.ValidateOrder(order);
36+
return this;
37+
}
38+
39+
/// <inheritdoc />
40+
public IServiceFilterAttributeTestBuilder AndAlso() => this;
41+
}
42+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Attributes
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using Microsoft.AspNetCore.Mvc;
7+
using Contracts.Attributes;
8+
using Internal.TestContexts;
9+
using Utilities;
10+
using Utilities.Extensions;
11+
12+
/// <summary>
13+
/// Used for testing <see cref="TypeFilterAttribute"/>.
14+
/// </summary>
15+
public class TypeFilterAttributeTestBuilder : BaseAttributeTestBuilderWithOrderAndType<TypeFilterAttribute>,
16+
IAndTypeFilterAttributeTestBuilder
17+
{
18+
/// <summary>
19+
/// Initializes a new instance of the <see cref="TypeFilterAttributeTestBuilder"/> class.
20+
/// </summary>
21+
/// <param name="testContext"><see cref="ComponentTestContext"/> containing data about the currently executed assertion chain.</param>
22+
/// <param name="failedValidationAction">Action to call in case of failed validation.</param>
23+
public TypeFilterAttributeTestBuilder(
24+
ComponentTestContext testContext,
25+
Action<string, string> failedValidationAction)
26+
: base(testContext, nameof(TypeFilterAttribute), failedValidationAction)
27+
=> this.Attribute = new TypeFilterAttribute(typeof(object));
28+
29+
/// <inheritdoc />
30+
public IAndTypeFilterAttributeTestBuilder OfType(Type type)
31+
{
32+
this.ValidateType(type, attr => attr.ImplementationType);
33+
return this;
34+
}
35+
36+
/// <inheritdoc />
37+
public IAndTypeFilterAttributeTestBuilder WithArguments(object[] args)
38+
{
39+
this.Validations.Add((expected, actual) =>
40+
{
41+
int expectedArgsCount = expected.Arguments.Length;
42+
int actualArgsCount = actual.Arguments != null ? actual.Arguments.Length : 0;
43+
44+
if (expectedArgsCount != actualArgsCount)
45+
{
46+
this.FailedValidationAction(
47+
$"{this.ExceptionMessagePrefix}{expectedArgsCount} {(actualArgsCount != 1 ? "arguments" : "argument")}",
48+
$"in fact found {actualArgsCount}");
49+
}
50+
});
51+
52+
args.ForEach(argument => this.WithArgument(argument));
53+
54+
return this;
55+
}
56+
57+
/// <inheritdoc />
58+
public IAndTypeFilterAttributeTestBuilder WithOrder(int order)
59+
{
60+
this.ValidateOrder(order);
61+
return this;
62+
}
63+
64+
/// <inheritdoc />
65+
public ITypeFilterAttributeTestBuilder AndAlso() => this;
66+
67+
private IAndTypeFilterAttributeTestBuilder WithArgument(object arg)
68+
{
69+
var args = new List<object>(this.Attribute.Arguments ?? new object[0])
70+
{
71+
arg
72+
};
73+
74+
this.Attribute.Arguments = args.ToArray();
75+
this.Validations.Add((expected, actual) =>
76+
{
77+
var sameEntry = actual.Arguments.FirstOrDefault(entry => Reflection.AreDeeplyEqual(arg, entry));
78+
if (sameEntry == null)
79+
{
80+
this.FailedValidationAction(
81+
$"{this.ExceptionMessagePrefix}argument with the provided value",
82+
"in fact such was not found");
83+
}
84+
});
85+
86+
return this;
87+
}
88+
}
89+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Attributes
2+
{
3+
/// <summary>
4+
/// Used for adding AndAlso() method to the <see cref="Microsoft.AspNetCore.Mvc.ServiceFilterAttribute"/> tests.
5+
/// </summary>
6+
public interface IAndServiceFilterAttributeTestBuilder : IServiceFilterAttributeTestBuilder
7+
{
8+
/// <summary>
9+
/// AndAlso method for better readability when testing <see cref="Microsoft.AspNetCore.Mvc.ServiceFilterAttribute"/>.
10+
/// </summary>
11+
/// <returns>The same <see cref="IServiceFilterAttributeTestBuilder"/>.</returns>
12+
IServiceFilterAttributeTestBuilder AndAlso();
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Attributes
2+
{
3+
/// <summary>
4+
/// Used for adding AndAlso() method to the <see cref="Microsoft.AspNetCore.Mvc.TypeFilterAttribute"/> tests.
5+
/// </summary>
6+
public interface IAndTypeFilterAttributeTestBuilder : ITypeFilterAttributeTestBuilder
7+
{
8+
/// <summary>
9+
/// AndAlso method for better readability when testing <see cref="Microsoft.AspNetCore.Mvc.TypeFilterAttribute"/>.
10+
/// </summary>
11+
/// <returns>The same <see cref="ITypeFilterAttributeTestBuilder"/>.</returns>
12+
ITypeFilterAttributeTestBuilder AndAlso();
13+
}
14+
}

src/MyTested.AspNetCore.Mvc.Controllers.Attributes/Builders/Contracts/Attributes/IMiddlewareFilterAttributeTestBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public interface IMiddlewareFilterAttributeTestBuilder : IBaseAttributeTestBuild
1212
/// has the same <see cref="Microsoft.AspNetCore.Mvc.MiddlewareFilterAttribute.ConfigurationType"/> value as the provided one.
1313
/// </summary>
1414
/// <param name="configurationType">A type which configures a middleware pipeline.</param>
15-
/// <returns>The same <see cref="IMiddlewareFilterAttributeTestBuilder"/>.</returns>
15+
/// <returns>The same <see cref="IAndMiddlewareFilterAttributeTestBuilder"/>.</returns>
1616
IAndMiddlewareFilterAttributeTestBuilder OfType(Type configurationType);
1717
}
1818
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Attributes
2+
{
3+
using System;
4+
5+
/// <summary>
6+
/// Used for testing <see cref="Microsoft.AspNetCore.Mvc.ServiceFilterAttribute"/>.
7+
/// </summary>
8+
public interface IServiceFilterAttributeTestBuilder : IBaseAttributeTestBuilderWithOrder<IAndServiceFilterAttributeTestBuilder>
9+
{
10+
/// <summary>
11+
/// Tests whether a <see cref="Microsoft.AspNetCore.Mvc.ServiceFilterAttribute"/>
12+
/// has the same <see cref="Microsoft.AspNetCore.Mvc.ServiceFilterAttribute.ServiceType"/> value as the provided one.
13+
/// </summary>
14+
/// <param name="type">The <see cref="Type"/> of filter to find.</param>
15+
/// <returns>The same <see cref="IAndServiceFilterAttributeTestBuilder"/>.</returns>
16+
IAndServiceFilterAttributeTestBuilder OfType(Type type);
17+
}
18+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Attributes
2+
{
3+
using System;
4+
5+
/// <summary>
6+
/// Used for testing <see cref="Microsoft.AspNetCore.Mvc.TypeFilterAttribute"/>.
7+
/// </summary>
8+
public interface ITypeFilterAttributeTestBuilder : IBaseAttributeTestBuilderWithOrder<IAndTypeFilterAttributeTestBuilder>
9+
{
10+
/// <summary>
11+
/// Tests whether a <see cref="Microsoft.AspNetCore.Mvc.TypeFilterAttribute"/>
12+
/// has the same <see cref="Microsoft.AspNetCore.Mvc.TypeFilterAttribute.ImplementationType"/> value as the provided one.
13+
/// </summary>
14+
/// <param name="type">The <see cref="Type"/> of filter to find.</param>
15+
/// <returns>The same <see cref="IAndTypeFilterAttributeTestBuilder"/>.</returns>
16+
IAndTypeFilterAttributeTestBuilder OfType(Type type);
17+
18+
/// <summary>
19+
/// Tests whether a <see cref="Microsoft.AspNetCore.Mvc.TypeFilterAttribute"/>
20+
/// contains the provided value in its <see cref="Microsoft.AspNetCore.Mvc.TypeFilterAttribute.Arguments"/> collection.
21+
/// </summary>
22+
/// <param name="args">Expected arguments.</param>
23+
/// <returns>The same attribute test builder.</returns>
24+
IAndTypeFilterAttributeTestBuilder WithArguments(object[] args);
25+
}
26+
}

src/MyTested.AspNetCore.Mvc.Controllers.Attributes/ControllerActionAttributesTestBuilderExtensions.cs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,106 @@ public static TAttributesTestBuilder SpecifyingMiddleware<TAttributesTestBuilder
430430
return actualBuilder.AttributesTestBuilder;
431431
}
432432

433+
/// <summary>
434+
/// Tests whether the collected attributes contain <see cref="ServiceFilterAttribute"/>.
435+
/// </summary>
436+
/// <param name="controllerActionAttributesTestBuilder">
437+
/// Instance of <see cref="IControllerActionAttributesTestBuilder{TAttributesTestBuilder}"/> type.
438+
/// </param>
439+
/// <param name="type">The <see cref="Type"/> of filter to find.</param>
440+
/// <returns>The same attributes test builder.</returns>
441+
public static TAttributesTestBuilder WithServiceFilter<TAttributesTestBuilder>(
442+
this IControllerActionAttributesTestBuilder<TAttributesTestBuilder> controllerActionAttributesTestBuilder,
443+
Type type)
444+
where TAttributesTestBuilder : IControllerActionAttributesTestBuilder<TAttributesTestBuilder>
445+
=> controllerActionAttributesTestBuilder
446+
.WithServiceFilter(filter => filter.OfType(type));
447+
448+
/// <summary>
449+
/// Tests whether the collected attributes contain <see cref="ServiceFilterAttribute"/>.
450+
/// </summary>
451+
/// <param name="controllerActionAttributesTestBuilder">
452+
/// Instance of <see cref="IControllerActionAttributesTestBuilder{TAttributesTestBuilder}"/> type.
453+
/// </param>
454+
/// <param name="serviceFilterAttributeBuilder">Expected <see cref="ServiceFilterAttribute"/> builder.</param>
455+
/// <returns>The same attributes test builder.</returns>
456+
public static TAttributesTestBuilder WithServiceFilter<TAttributesTestBuilder>(
457+
this IControllerActionAttributesTestBuilder<TAttributesTestBuilder> controllerActionAttributesTestBuilder,
458+
Action<IServiceFilterAttributeTestBuilder> serviceFilterAttributeBuilder)
459+
where TAttributesTestBuilder : IControllerActionAttributesTestBuilder<TAttributesTestBuilder>
460+
{
461+
var actualBuilder = (BaseAttributesTestBuilder<TAttributesTestBuilder>)controllerActionAttributesTestBuilder;
462+
463+
actualBuilder.ContainingAttributeOfType<ServiceFilterAttribute>();
464+
465+
actualBuilder.Validations.Add(attrs =>
466+
{
467+
var newServiceFilterAttributeBuilder = new ServiceFilterAttributeTestBuilder(
468+
actualBuilder.TestContext,
469+
actualBuilder.ThrowNewAttributeAssertionException);
470+
471+
serviceFilterAttributeBuilder(newServiceFilterAttributeBuilder);
472+
473+
var expectedAttribute = newServiceFilterAttributeBuilder.GetAttribute();
474+
var actualAttribute = actualBuilder.GetAttributeOfType<ServiceFilterAttribute>(attrs);
475+
476+
var validations = newServiceFilterAttributeBuilder.GetAttributeValidations();
477+
validations.ForEach(v => v(expectedAttribute, actualAttribute));
478+
});
479+
480+
return actualBuilder.AttributesTestBuilder;
481+
}
482+
483+
/// <summary>
484+
/// Tests whether the collected attributes contain <see cref="TypeFilterAttribute"/>.
485+
/// </summary>
486+
/// <param name="controllerActionAttributesTestBuilder">
487+
/// Instance of <see cref="IControllerActionAttributesTestBuilder{TAttributesTestBuilder}"/> type.
488+
/// </param>
489+
/// <param name="type">The <see cref="Type"/> of filter to create.</param>
490+
/// <returns>The same attributes test builder.</returns>
491+
public static TAttributesTestBuilder WithTypeFilter<TAttributesTestBuilder>(
492+
this IControllerActionAttributesTestBuilder<TAttributesTestBuilder> controllerActionAttributesTestBuilder,
493+
Type type)
494+
where TAttributesTestBuilder : IControllerActionAttributesTestBuilder<TAttributesTestBuilder>
495+
=> controllerActionAttributesTestBuilder
496+
.WithTypeFilter(filter => filter.OfType(type));
497+
498+
/// <summary>
499+
/// Tests whether the collected attributes contain <see cref="TypeFilterAttribute"/>.
500+
/// </summary>
501+
/// <param name="controllerActionAttributesTestBuilder">
502+
/// Instance of <see cref="IControllerActionAttributesTestBuilder{TAttributesTestBuilder}"/> type.
503+
/// </param>
504+
/// <param name="typeFilterAttributeBuilder">Expected <see cref="TypeFilterAttribute"/> builder.</param>
505+
/// <returns>The same attributes test builder.</returns>
506+
public static TAttributesTestBuilder WithTypeFilter<TAttributesTestBuilder>(
507+
this IControllerActionAttributesTestBuilder<TAttributesTestBuilder> controllerActionAttributesTestBuilder,
508+
Action<ITypeFilterAttributeTestBuilder> typeFilterAttributeBuilder)
509+
where TAttributesTestBuilder : IControllerActionAttributesTestBuilder<TAttributesTestBuilder>
510+
{
511+
var actualBuilder = (BaseAttributesTestBuilder<TAttributesTestBuilder>)controllerActionAttributesTestBuilder;
512+
513+
actualBuilder.ContainingAttributeOfType<TypeFilterAttribute>();
514+
515+
actualBuilder.Validations.Add(attrs =>
516+
{
517+
var newTypeFilterAttributeBuilder = new TypeFilterAttributeTestBuilder(
518+
actualBuilder.TestContext,
519+
actualBuilder.ThrowNewAttributeAssertionException);
520+
521+
typeFilterAttributeBuilder(newTypeFilterAttributeBuilder);
522+
523+
var expectedAttribute = newTypeFilterAttributeBuilder.GetAttribute();
524+
var actualAttribute = actualBuilder.GetAttributeOfType<TypeFilterAttribute>(attrs);
525+
526+
var validations = newTypeFilterAttributeBuilder.GetAttributeValidations();
527+
validations.ForEach(v => v(expectedAttribute, actualAttribute));
528+
});
529+
530+
return actualBuilder.AttributesTestBuilder;
531+
}
532+
433533
/// <summary>
434534
/// Tests whether the collected attributes contain <see cref="RequireHttpsAttribute"/>.
435535
/// </summary>

0 commit comments

Comments
 (0)