Skip to content

Commit 5d38882

Browse files
committed
Added generic version of the ShouldPassFor (#181)
1 parent 9cae77c commit 5d38882

File tree

17 files changed

+910
-42
lines changed

17 files changed

+910
-42
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.And
2+
{
3+
using Base;
4+
using Contracts.And;
5+
using Contracts.Base;
6+
using Internal.TestContexts;
7+
8+
/// <summary>
9+
/// AndAlso method for better readability when chaining should pass for tests.
10+
/// </summary>
11+
public class AndTestBuilder : BaseTestBuilderWithComponent, IAndTestBuilder
12+
{
13+
public AndTestBuilder(ComponentTestContext testContext)
14+
: base(testContext)
15+
{
16+
}
17+
18+
/// <inheritdoc />
19+
public IBaseTestBuilderWithComponent AndAlso() => this;
20+
}
21+
}

src/MyTested.AspNetCore.Mvc.Abstractions/Builders/Base/BaseTestBuilder.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
using Licensing;
77
using Microsoft.AspNetCore.Http;
88
using ShouldPassFor;
9+
using System;
10+
using System.Reflection;
911
using Utilities.Validators;
1012

1113
/// <summary>

src/MyTested.AspNetCore.Mvc.Abstractions/Builders/Base/BaseTestBuilderWithComponent.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
namespace MyTested.AspNetCore.Mvc.Builders.Base
22
{
33
using System;
4-
using System.Collections.Generic;
4+
using Contracts.And;
55
using Contracts.Base;
6+
using Exceptions;
7+
using Internal;
68
using Internal.TestContexts;
9+
using Utilities;
710
using Utilities.Validators;
11+
using And;
812

913
/// <summary>
1014
/// Base class for all test builders with component.
@@ -22,7 +26,7 @@ protected BaseTestBuilderWithComponent(ComponentTestContext testContext)
2226
{
2327
this.TestContext = testContext;
2428
}
25-
29+
2630
/// <summary>
2731
/// Gets the currently used <see cref="ComponentTestContext"/>.
2832
/// </summary>
@@ -40,5 +44,25 @@ private set
4044
this.testContext = value;
4145
}
4246
}
47+
48+
/// <inheritdoc />
49+
public IAndTestBuilder ShouldPassForThe<TComponent>(Action<TComponent> assertions)
50+
where TComponent : class
51+
{
52+
assertions(TestHelper.TryGetShouldPassForValue<TComponent>(this.TestContext));
53+
return new AndTestBuilder(this.TestContext);
54+
}
55+
56+
/// <inheritdoc />
57+
public IAndTestBuilder ShouldPassForThe<TComponent>(Func<TComponent, bool> predicate)
58+
where TComponent : class
59+
{
60+
if (!predicate(TestHelper.TryGetShouldPassForValue<TComponent>(this.TestContext)))
61+
{
62+
throw new InvalidAssertionException($"Expected {typeof(TComponent).ToFriendlyTypeName()} to pass the given predicate but it failed.");
63+
}
64+
65+
return new AndTestBuilder(this.TestContext);
66+
}
4367
}
4468
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.And
2+
{
3+
using Base;
4+
5+
/// <summary>
6+
/// Used for adding 'AndAlso' method to <see cref="IBaseTestBuilderWithComponent"/>.
7+
/// </summary>
8+
public interface IAndTestBuilder : IBaseTestBuilderWithComponent
9+
{
10+
/// <summary>
11+
/// AndAlso method for better readability when chaining should pass for tests.
12+
/// </summary>
13+
/// <returns>The same <see cref="IBaseTestBuilderWithComponent"/>.</returns>
14+
IBaseTestBuilderWithComponent AndAlso();
15+
}
16+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,29 @@
11
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Base
22
{
3+
using System;
4+
using And;
5+
36
/// <summary>
47
/// Base class for all test builders with component.
58
/// </summary>
69
public interface IBaseTestBuilderWithComponent : IBaseTestBuilder
710
{
11+
/// <summary>
12+
/// Tests whether the provided component type passes the given assertions.
13+
/// </summary>
14+
/// <typeparam name="TComponent">Type of component to test.</typeparam>
15+
/// <param name="assertions">Action containing assertions on the provided component.</param>
16+
/// <returns>The same <see cref="IBaseTestBuilderWithComponent"/>.</returns>
17+
IAndTestBuilder ShouldPassForThe<TComponent>(Action<TComponent> assertions)
18+
where TComponent : class;
19+
20+
/// <summary>
21+
/// Tests whether the provided component passes the given predicate.
22+
/// </summary>
23+
/// <typeparam name="TComponent">Type of component to test.</typeparam>
24+
/// <param name="predicate">Predicate testing the provided component.</param>
25+
/// <returns>The same <see cref="IBaseTestBuilderWithComponent"/>.</returns>
26+
IAndTestBuilder ShouldPassForThe<TComponent>(Func<TComponent, bool> predicate)
27+
where TComponent : class;
828
}
929
}

src/MyTested.AspNetCore.Mvc.Abstractions/Builders/Contracts/Base/IBaseTestBuilderWithComponentBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Base
22
{
3-
public interface IBaseTestBuilderWithComponentBuilder<TBuilder> : IBaseTestBuilder
3+
public interface IBaseTestBuilderWithComponentBuilder<TBuilder> : IBaseTestBuilderWithComponent
44
where TBuilder : IBaseTestBuilder
55
{
66
}

src/MyTested.AspNetCore.Mvc.Abstractions/Internal/Application/TestApplication.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
public static class TestApplication
3030
{
3131
private const string TestFrameworkName = "MyTested.AspNetCore.Mvc";
32-
private const string ReleaseDate = "2016-06-01";
32+
private const string ReleaseDate = "2016-09-01";
3333

3434
private static readonly RequestDelegate NullHandler;
3535

@@ -227,6 +227,12 @@ internal static void LoadPlugins()
227227
{
228228
TestHelper.HttpFeatureRegistrationPlugins.Add(httpFeatureRegistrationPlugin);
229229
}
230+
231+
var shouldPassForPlugin = plugin as IShouldPassForPlugin;
232+
if (shouldPassForPlugin != null)
233+
{
234+
TestHelper.ShouldPassForPlugins.Add(shouldPassForPlugin);
235+
}
230236
});
231237
}
232238

src/MyTested.AspNetCore.Mvc.Abstractions/Internal/TestHelper.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@
77
using Microsoft.AspNetCore.Http.Features;
88
using Plugins;
99
using Services;
10+
using TestContexts;
11+
using Utilities;
1012

1113
public static class TestHelper
1214
{
1315
public static Action GlobalTestCleanup { get; set; }
1416

1517
public static ISet<IHttpFeatureRegistrationPlugin> HttpFeatureRegistrationPlugins { get; }
1618
= new HashSet<IHttpFeatureRegistrationPlugin>();
19+
20+
public static ISet<IShouldPassForPlugin> ShouldPassForPlugins { get; }
21+
= new HashSet<IShouldPassForPlugin>();
1722

1823
public static MockedHttpContext CreateMockedHttpContext()
1924
{
@@ -44,6 +49,21 @@ public static void SetHttpContextToAccessor(HttpContext httpContext)
4449
}
4550
}
4651

52+
public static TComponent TryGetShouldPassForValue<TComponent>(ComponentTestContext testContext)
53+
where TComponent : class
54+
{
55+
foreach (var shouldPassForPlugin in ShouldPassForPlugins)
56+
{
57+
var result = shouldPassForPlugin.TryGetValue(typeof(TComponent), testContext) as TComponent;
58+
if (result != null)
59+
{
60+
return result;
61+
}
62+
}
63+
64+
throw new InvalidOperationException($"{typeof(TComponent).ToFriendlyTypeName()} could not be resolved for the 'ShouldPassForThe<TComponent>' method call.");
65+
}
66+
4767
public static void ExecuteTestCleanup() => GlobalTestCleanup?.Invoke();
4868
}
4969
}

src/MyTested.AspNetCore.Mvc.Abstractions/Plugins/AbstractionsTestPlugin.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,35 @@
22
{
33
using System;
44
using Internal.Contracts;
5+
using Internal.TestContexts;
56
using Microsoft.Extensions.DependencyInjection;
7+
using Utilities;
8+
using Microsoft.AspNetCore.Http;
69

7-
public class AbstractionsTestPlugin : BaseTestPlugin, IServiceRegistrationPlugin, IInitializationPlugin
10+
public class AbstractionsTestPlugin : BaseTestPlugin, IServiceRegistrationPlugin, IInitializationPlugin, IShouldPassForPlugin
811
{
12+
private readonly Type baseHttpContextType = typeof(HttpContext);
13+
private readonly Type baseHttpRequestType = typeof(HttpRequest);
14+
915
public Action<IServiceCollection> ServiceRegistrationDelegate =>
1016
serviceCollection => serviceCollection.AddCoreTesting();
1117

1218
// this call prepares all application conventions and fills the controller action descriptor cache
1319
public Action<IServiceProvider> InitializationDelegate => serviceProvider => serviceProvider.GetService<IControllerActionDescriptorCache>();
20+
21+
public object TryGetValue(Type type, ComponentTestContext testContext)
22+
{
23+
if (Reflection.AreAssignable(baseHttpContextType, type))
24+
{
25+
return testContext.HttpContext;
26+
}
27+
28+
if (Reflection.AreAssignable(baseHttpRequestType, type))
29+
{
30+
return testContext.HttpRequest;
31+
}
32+
33+
return null;
34+
}
1435
}
1536
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace MyTested.AspNetCore.Mvc.Plugins
2+
{
3+
using System;
4+
using Internal.TestContexts;
5+
6+
public interface IShouldPassForPlugin
7+
{
8+
object TryGetValue(Type type, ComponentTestContext testContext);
9+
}
10+
}

0 commit comments

Comments
 (0)