Skip to content

Commit bf42979

Browse files
committed
Added a value provider for pipeline tests - one which ignores the value during route assertion but uses it within the action call (closes #385)
1 parent 545ae35 commit bf42979

File tree

6 files changed

+186
-7
lines changed

6 files changed

+186
-7
lines changed

src/MyTested.AspNetCore.Mvc.Abstractions/From.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@
88
/// </summary>
99
public static class From
1010
{
11-
static From()
12-
{
13-
TestApplication.TryInitialize();
14-
}
11+
static From() => TestApplication.TryInitialize();
1512

1613
/// <summary>
1714
/// Indicates that a argument should be resolved from the application <see cref="System.IServiceProvider"/> in a method call lambda expression.

src/MyTested.AspNetCore.Mvc.Abstractions/Utilities/ExpressionParser.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ public static object ResolveExpressionValue(Expression expression)
8383
// These expressions types should be ignored and can be skipped:
8484
// - c => c.Action(With.No<int>())
8585
// - c => c.Action(With.Any<int>())
86+
// - c => c.Action(With.Value(value))
87+
// - c => c.Action(With.IgnoredRouteValue(value))
8688
// - c => c.Action(From.Services<IService>())
8789
var expressionArgumentAsMethodCall = (MethodCallExpression)expression;
8890
var expressionMethodDeclaringType = expressionArgumentAsMethodCall.Method.DeclaringType;
@@ -92,7 +94,9 @@ public static object ResolveExpressionValue(Expression expression)
9294
var expressionArgumentMethodName = expressionArgumentAsMethodCall.Method.Name;
9395

9496
if (expressionMethodDeclaringType == TypeOfWith
95-
&& expressionArgumentMethodName == nameof(With.Any))
97+
&& (expressionArgumentMethodName == nameof(With.Any)
98+
|| expressionArgumentMethodName == nameof(With.Value)
99+
|| expressionArgumentMethodName == nameof(With.IgnoredRouteValue)))
96100
{
97101
return IgnoredExpressionArgument;
98102
}

src/MyTested.AspNetCore.Mvc.Abstractions/With.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,38 @@ public static TParameter Empty<TParameter>()
2424
=> new TParameter();
2525

2626
/// <summary>
27-
/// Indicates that a argument should not be considered in method call lambda expression.
27+
/// Indicates that an argument should not be considered in method call lambda expression.
2828
/// </summary>
2929
/// <typeparam name="TParameter">Type of parameter.</typeparam>
3030
/// <returns>Default value of the parameter.</returns>
3131
public static TParameter No<TParameter>()
3232
=> default(TParameter);
3333

3434
/// <summary>
35-
/// Indicates that a argument should not be considered in method call lambda expression.
35+
/// Indicates that an argument should not be considered in method call lambda expression.
3636
/// </summary>
3737
/// <typeparam name="TParameter">Type of parameter.</typeparam>
3838
/// <returns>Default value of the parameter.</returns>
3939
/// <remarks>Using this method in route testing will indicate that the route value should be ignored during the test.</remarks>
4040
public static TParameter Any<TParameter>()
4141
=> default(TParameter);
42+
43+
/// <summary>
44+
/// Indicates that a argument should not be considered during a route test but used in the actual action call. This method is the same as <see cref="With.IgnoredRouteValue{TParameter}(TParameter)"/>
45+
/// </summary>
46+
/// <typeparam name="TParameter">Type of parameter.</typeparam>
47+
/// <returns>The provided value.</returns>
48+
/// <remarks>Using this method in pipeline testing will indicate that the route value should be ignored during the route test but used during the action execution.</remarks>
49+
public static TParameter Value<TParameter>(TParameter value)
50+
=> value;
51+
52+
/// <summary>
53+
/// Indicates that a argument should not be considered during a route test but used in the actual action call. This method is the same as <see cref="With.Value{TParameter}(TParameter)"/>.
54+
/// </summary>
55+
/// <typeparam name="TParameter">Type of parameter.</typeparam>
56+
/// <returns>The provided value.</returns>
57+
/// <remarks>Using this method in pipeline testing will indicate that the route value should be ignored during the route test but used during the action execution.</remarks>
58+
public static TParameter IgnoredRouteValue<TParameter>(TParameter value)
59+
=> value;
4260
}
4361
}

test/MyTested.AspNetCore.Mvc.Pipeline.Test/BuildersTests/PipelineTests/WhichControllerInstanceBuilderTests.cs

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace MyTested.AspNetCore.Mvc.Test.BuildersTests.PipelineTests
22
{
3+
using System.Threading;
34
using Exceptions;
45
using Microsoft.Extensions.DependencyInjection;
56
using Setups;
@@ -62,6 +63,136 @@ public void WhichShouldResolveCorrectEmptyAsyncAction()
6263
.ShouldReturnEmpty();
6364
}
6465

66+
[Fact]
67+
public void WhichShouldResolveCorrectActionWithIgnoredRouteValue()
68+
{
69+
MyPipeline
70+
.Configuration()
71+
.ShouldMap("/Home/Contact/1")
72+
.To<HomeController>(c => c.Contact(With.Value(2)))
73+
.Which()
74+
.ShouldReturn()
75+
.Ok(ok => ok
76+
.Passing(result => result
77+
.Value
78+
.Equals(2)));
79+
}
80+
81+
[Fact]
82+
public void WhichShouldResolveCorrectActionWithIgnoredRouteValueLongName()
83+
{
84+
MyPipeline
85+
.Configuration()
86+
.ShouldMap("/Home/Contact/1")
87+
.To<HomeController>(c => c.Contact(With.IgnoredRouteValue(2)))
88+
.Which()
89+
.ShouldReturn()
90+
.Ok(ok => ok
91+
.Passing(result => result
92+
.Value
93+
.Equals(2)));
94+
}
95+
96+
[Fact]
97+
public void WhichShouldResolveCorrectActionWithIgnoredCancellationTokenCancelled()
98+
{
99+
MyPipeline
100+
.Configuration()
101+
.ShouldMap("/Home/CancelledTask/1")
102+
.To<HomeController>(c => c.CancelledTask(1, With.Value(new CancellationToken(true))))
103+
.Which()
104+
.ShouldReturn()
105+
.Ok(ok => ok
106+
.Passing(result => result
107+
.Value
108+
.Equals("Cancelled with id: 1")));
109+
}
110+
111+
[Fact]
112+
public void WhichShouldResolveCorrectActionWithIgnoredCancellationTokenLongNameCancelled()
113+
{
114+
MyPipeline
115+
.Configuration()
116+
.ShouldMap("/Home/CancelledTask/1")
117+
.To<HomeController>(c => c.CancelledTask(1, With.IgnoredRouteValue(new CancellationToken(true))))
118+
.Which()
119+
.ShouldReturn()
120+
.Ok(ok => ok
121+
.Passing(result => result
122+
.Value
123+
.Equals("Cancelled with id: 1")));
124+
}
125+
126+
[Fact]
127+
public void WhichShouldResolveCorrectActionWithIgnoredCancellationToken()
128+
{
129+
MyPipeline
130+
.Configuration()
131+
.ShouldMap("/Home/CancelledTask/1")
132+
.To<HomeController>(c => c.CancelledTask(1, With.Value(new CancellationToken(false))))
133+
.Which()
134+
.ShouldReturn()
135+
.Ok(ok => ok
136+
.Passing(result => result
137+
.Value
138+
.Equals(1)));
139+
}
140+
141+
[Fact]
142+
public void WhichShouldResolveCorrectActionWithIgnoredCancellationTokenLongName()
143+
{
144+
MyPipeline
145+
.Configuration()
146+
.ShouldMap("/Home/CancelledTask/1")
147+
.To<HomeController>(c => c.CancelledTask(1, With.IgnoredRouteValue(new CancellationToken(false))))
148+
.Which()
149+
.ShouldReturn()
150+
.Ok(ok => ok
151+
.Passing(result => result
152+
.Value
153+
.Equals(1)));
154+
}
155+
156+
[Fact]
157+
public void WhichShouldResolveCorrectActionValuesWithIgnoredCancellationToken()
158+
{
159+
Test.AssertException<RouteAssertionException>(
160+
() =>
161+
{
162+
MyPipeline
163+
.Configuration()
164+
.ShouldMap("/Home/CancelledTask/1")
165+
.To<HomeController>(c => c.CancelledTask(2, With.Value(new CancellationToken(false))))
166+
.Which()
167+
.ShouldReturn()
168+
.Ok(ok => ok
169+
.Passing(result => result
170+
.Value
171+
.Equals(2)));
172+
},
173+
"Expected route '/Home/CancelledTask/1' to contain route value with 'id' key and the provided value but the value was different. Expected a value of '2', but in fact it was '1'.");
174+
}
175+
176+
[Fact]
177+
public void WhichShouldResolveCorrectActionValuesWithIgnoredCancellationTokenLongName()
178+
{
179+
Test.AssertException<RouteAssertionException>(
180+
() =>
181+
{
182+
MyPipeline
183+
.Configuration()
184+
.ShouldMap("/Home/CancelledTask/1")
185+
.To<HomeController>(c => c.CancelledTask(2, With.IgnoredRouteValue(new CancellationToken(false))))
186+
.Which()
187+
.ShouldReturn()
188+
.Ok(ok => ok
189+
.Passing(result => result
190+
.Value
191+
.Equals(2)));
192+
},
193+
"Expected route '/Home/CancelledTask/1' to contain route value with 'id' key and the provided value but the value was different. Expected a value of '2', but in fact it was '1'.");
194+
}
195+
65196
[Fact]
66197
public void WhichShouldResolveCorrectAsyncActionWithSetup()
67198
{

test/MyTested.AspNetCore.Mvc.Routing.Test/BuildersTests/RoutingTests/RouteTestBuilderTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,24 @@ public void ToShouldResolveCorrectlyWithIgnoredParameter()
431431
.To<HomeController>(c => c.Contact(With.Any<int>()));
432432
}
433433

434+
[Fact]
435+
public void ToShouldResolveCorrectlyWithIgnoredParameterButActualValue()
436+
{
437+
MyRouting
438+
.Configuration()
439+
.ShouldMap("/Home/Contact/1")
440+
.To<HomeController>(c => c.Contact(With.Value(2)));
441+
}
442+
443+
[Fact]
444+
public void ToShouldResolveCorrectlyWithIgnoredParameterButActualValueLongName()
445+
{
446+
MyRouting
447+
.Configuration()
448+
.ShouldMap("/Home/Contact/1")
449+
.To<HomeController>(c => c.Contact(With.IgnoredRouteValue(2)));
450+
}
451+
434452
[Fact]
435453
public void ToShouldResolveCorrectControllerAndActionWithNoModel()
436454
{

test/MyTested.AspNetCore.Mvc.Test.Setups/Routing/HomeController.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
namespace MyTested.AspNetCore.Mvc.Test.Setups.Routing
22
{
33
using System;
4+
using System.Threading;
45
using System.Threading.Tasks;
56
using Microsoft.AspNetCore.Mvc;
67

@@ -21,5 +22,15 @@ public IActionResult FailingAction()
2122
public void Empty() { }
2223

2324
public async Task EmptyTask() => await Task.CompletedTask;
25+
26+
public async Task<IActionResult> CancelledTask(int id, CancellationToken cancellationToken)
27+
{
28+
if (cancellationToken.IsCancellationRequested)
29+
{
30+
return await Task.FromResult(Ok($"Cancelled with id: {id}"));
31+
}
32+
33+
return await Task.FromResult(Ok(id));
34+
}
2435
}
2536
}

0 commit comments

Comments
 (0)