Skip to content

Commit 008e484

Browse files
committed
Extracted method invocation in BaseComponentInvocationBuilder (#66)
1 parent 6c78359 commit 008e484

9 files changed

Lines changed: 179 additions & 127 deletions

File tree

src/MyTested.AspNetCore.Mvc.Abstractions/Builders/Components/BaseComponentBuilder.cs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,14 @@
1212
using Utilities;
1313
using Utilities.Validators;
1414

15-
public abstract class BaseComponentBuilder<TComponent, TTestContext, TBuilder> : BaseTestBuilderWithComponentBuilder<TBuilder>
15+
public abstract partial class BaseComponentBuilder<TComponent, TTestContext, TBuilder> : BaseTestBuilderWithComponentBuilder<TBuilder>
1616
where TComponent : class
1717
where TTestContext : ComponentTestContext
1818
where TBuilder : IBaseTestBuilder
1919
{
2020
private TTestContext testContext;
2121
private bool isPreparedForTesting;
2222

23-
private Action<TComponent> componentSetupAction;
24-
2523
public BaseComponentBuilder(TTestContext testContext)
2624
: base(testContext)
2725
{
@@ -68,13 +66,7 @@ protected TComponent Component
6866

6967
protected bool SkipComponentActivation { get; set; }
7068

71-
public TBuilder WithSetup(Action<TComponent> componentSetup)
72-
{
73-
this.componentSetupAction += componentSetup;
74-
return this.Builder;
75-
}
76-
77-
protected virtual void BuildComponentIfNotExists()
69+
protected void BuildComponentIfNotExists()
7870
{
7971
if (!this.isPreparedForTesting)
8072
{
@@ -144,8 +136,6 @@ protected void ValidateComponentType()
144136
}
145137
}
146138

147-
protected abstract void PrepareComponentContext();
148-
149139
protected abstract TComponent TryCreateComponentWithFactory();
150140

151141
protected abstract void ActivateComponent();
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Components
2+
{
3+
using System;
4+
using System.Linq.Expressions;
5+
using System.Threading.Tasks;
6+
using Internal;
7+
using Internal.TestContexts;
8+
using Utilities;
9+
using System.Reflection;
10+
11+
public partial class BaseComponentBuilder<TComponent, TTestContext, TBuilder>
12+
{
13+
protected void Invoke<TMethodResult>(Expression<Func<TComponent, TMethodResult>> methodCall)
14+
{
15+
var actionInfo = this.GetAndValidateMethodResult(methodCall);
16+
this.TestContext.Apply(actionInfo);
17+
}
18+
19+
protected void Invoke<TMethodResult>(Expression<Func<TComponent, Task<TMethodResult>>> methodCall)
20+
{
21+
var methodInfo = this.GetAndValidateMethodResult(methodCall);
22+
var methodResult = default(TMethodResult);
23+
24+
try
25+
{
26+
methodResult = AsyncHelper.RunSync(() => methodInfo.MethodResult);
27+
}
28+
catch (Exception exception)
29+
{
30+
methodInfo.CaughtException = new AggregateException(exception);
31+
}
32+
33+
this.TestContext.Apply(methodInfo);
34+
this.TestContext.MethodResult = methodResult;
35+
}
36+
37+
protected void Invoke(Expression<Action<TComponent>> methodCall)
38+
{
39+
var methodName = this.GetAndValidateMethod(methodCall);
40+
Exception caughtException = null;
41+
42+
try
43+
{
44+
methodCall.Compile().Invoke(this.Component);
45+
}
46+
catch (Exception exception)
47+
{
48+
caughtException = exception;
49+
}
50+
51+
this.TestContext.MethodName = methodName;
52+
this.TestContext.MethodCall = methodCall;
53+
this.TestContext.CaughtException = caughtException;
54+
this.TestContext.MethodResult = VoidMethodResult.Instance;
55+
}
56+
57+
protected void Invoke(Expression<Func<TComponent, Task>> methodCall)
58+
{
59+
var methodInfo = this.GetAndValidateMethodResult(methodCall);
60+
61+
try
62+
{
63+
AsyncHelper.RunSync(() => methodInfo.MethodResult);
64+
}
65+
catch (Exception exception)
66+
{
67+
methodInfo.CaughtException = new AggregateException(exception);
68+
}
69+
70+
this.TestContext.Apply(methodInfo);
71+
this.TestContext.MethodResult = VoidMethodResult.Instance;
72+
}
73+
74+
protected abstract void ProcessAndValidateMethod(LambdaExpression methodCall, MethodInfo methodInfo);
75+
76+
private InvocationTestContext<TMethodResult> GetAndValidateMethodResult<TMethodResult>(Expression<Func<TComponent, TMethodResult>> methodCall)
77+
{
78+
var methodName = this.GetAndValidateMethod(methodCall);
79+
var methodResult = default(TMethodResult);
80+
Exception caughtException = null;
81+
82+
try
83+
{
84+
methodResult = methodCall.Compile().Invoke(this.Component);
85+
}
86+
catch (Exception exception)
87+
{
88+
caughtException = exception;
89+
}
90+
91+
return new InvocationTestContext<TMethodResult>(methodName, methodCall, methodResult, caughtException);
92+
}
93+
94+
private string GetAndValidateMethod(LambdaExpression methodCall)
95+
{
96+
this.TestContext.ComponentBuildDelegate?.Invoke();
97+
98+
this.TestContext.MethodCall = methodCall;
99+
this.TestContext.PreMethodInvocationDelegate?.Invoke();
100+
101+
var methodInfo = ExpressionParser.GetMethodInfo(methodCall);
102+
103+
this.ProcessAndValidateMethod(methodCall, methodInfo);
104+
105+
return methodInfo.Name;
106+
}
107+
}
108+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Components
2+
{
3+
using System;
4+
5+
public partial class BaseComponentBuilder<TComponent, TTestContext, TBuilder>
6+
{
7+
private Action<TComponent> componentSetupAction;
8+
9+
/// <inheritdoc />
10+
public TBuilder WithSetup(Action<TComponent> componentSetup)
11+
{
12+
this.componentSetupAction += componentSetup;
13+
return this.Builder;
14+
}
15+
16+
protected abstract void PrepareComponentContext();
17+
}
18+
}

src/MyTested.AspNetCore.Mvc.Abstractions/Internal/TestContexts/ActionTestContext.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,5 @@ public TComponentContext ComponentContext
6666
public Action<TComponentContext> ComponentContextPreparationDelegate { get; set; }
6767

6868
protected abstract TComponentContext DefaultComponentContext { get; }
69-
70-
public void Apply<TMethodResult>(InvocationTestContext<TMethodResult> invocationTestContext)
71-
{
72-
this.MethodName = invocationTestContext.MethodName;
73-
this.MethodCall = invocationTestContext.MethodCall;
74-
this.MethodResult = invocationTestContext.MethodResult;
75-
this.CaughtException = invocationTestContext.CaughtException;
76-
}
7769
}
7870
}

src/MyTested.AspNetCore.Mvc.Abstractions/Internal/TestContexts/ComponentTestContext.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,5 +151,13 @@ public TException CaughtExceptionAs<TException>()
151151
where TException : Exception => this.CaughtException as TException;
152152

153153
public TModel ModelAs<TModel>() => this.Model.TryCastTo<TModel>();
154+
155+
public void Apply<TMethodResult>(InvocationTestContext<TMethodResult> invocationTestContext)
156+
{
157+
this.MethodName = invocationTestContext.MethodName;
158+
this.MethodCall = invocationTestContext.MethodCall;
159+
this.MethodResult = invocationTestContext.MethodResult;
160+
this.CaughtException = invocationTestContext.CaughtException;
161+
}
154162
}
155163
}

src/MyTested.AspNetCore.Mvc.Controllers/Builders/Controllers/ControllerActionCallBuilder.cs

Lines changed: 7 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@
88
using Actions;
99
using Contracts.Actions;
1010
using Internal.Contracts;
11-
using Internal.TestContexts;
1211
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
1312
using Microsoft.Extensions.DependencyInjection;
1413
using Utilities;
1514
using Utilities.Extensions;
16-
using Internal;
1715

1816
/// <content>
1917
/// Used for building the controller which will be tested.
@@ -23,112 +21,39 @@ public partial class ControllerBuilder<TController>
2321
/// <inheritdoc />
2422
public IActionResultTestBuilder<TActionResult> Calling<TActionResult>(Expression<Func<TController, TActionResult>> actionCall)
2523
{
26-
var actionInfo = this.GetAndValidateActionResult(actionCall);
27-
28-
this.TestContext.Apply(actionInfo);
29-
24+
this.Invoke(actionCall);
3025
return new ActionResultTestBuilder<TActionResult>(this.TestContext);
3126
}
3227

3328
/// <inheritdoc />
3429
public IActionResultTestBuilder<TActionResult> Calling<TActionResult>(Expression<Func<TController, Task<TActionResult>>> actionCall)
3530
{
36-
var actionInfo = this.GetAndValidateActionResult(actionCall);
37-
var actionResult = default(TActionResult);
38-
39-
try
40-
{
41-
actionResult = AsyncHelper.RunSync(() => actionInfo.MethodResult);
42-
}
43-
catch (Exception exception)
44-
{
45-
actionInfo.CaughtException = new AggregateException(exception);
46-
}
47-
48-
this.TestContext.Apply(actionInfo);
49-
this.TestContext.MethodResult = actionResult;
50-
31+
this.Invoke(actionCall);
5132
return new ActionResultTestBuilder<TActionResult>(this.TestContext);
5233
}
5334

5435
/// <inheritdoc />
5536
public IVoidActionResultTestBuilder Calling(Expression<Action<TController>> actionCall)
5637
{
57-
var actionName = this.GetAndValidateAction(actionCall);
58-
Exception caughtException = null;
59-
60-
try
61-
{
62-
actionCall.Compile().Invoke(this.Component);
63-
}
64-
catch (Exception exception)
65-
{
66-
caughtException = exception;
67-
}
68-
69-
this.TestContext.MethodName = actionName;
70-
this.TestContext.MethodCall = actionCall;
71-
this.TestContext.CaughtException = caughtException;
72-
this.TestContext.MethodResult = VoidMethodResult.Instance;
73-
38+
this.Invoke(actionCall);
7439
return new VoidActionResultTestBuilder(this.TestContext);
7540
}
7641

7742
/// <inheritdoc />
7843
public IVoidActionResultTestBuilder Calling(Expression<Func<TController, Task>> actionCall)
7944
{
80-
var actionInfo = this.GetAndValidateActionResult(actionCall);
81-
82-
try
83-
{
84-
AsyncHelper.RunSync(() => actionInfo.MethodResult);
85-
}
86-
catch (Exception exception)
87-
{
88-
actionInfo.CaughtException = new AggregateException(exception);
89-
}
90-
91-
this.TestContext.Apply(actionInfo);
92-
this.TestContext.MethodResult = VoidMethodResult.Instance;
93-
45+
this.Invoke(actionCall);
9446
return new VoidActionResultTestBuilder(this.TestContext);
9547
}
9648

97-
private InvocationTestContext<TActionResult> GetAndValidateActionResult<TActionResult>(Expression<Func<TController, TActionResult>> actionCall)
98-
{
99-
var actionName = this.GetAndValidateAction(actionCall);
100-
var actionResult = default(TActionResult);
101-
Exception caughtException = null;
102-
103-
try
104-
{
105-
actionResult = actionCall.Compile().Invoke(this.Component);
106-
}
107-
catch (Exception exception)
108-
{
109-
caughtException = exception;
110-
}
111-
112-
return new InvocationTestContext<TActionResult>(actionName, actionCall, actionResult, caughtException);
113-
}
114-
115-
private string GetAndValidateAction(LambdaExpression actionCall)
49+
protected override void ProcessAndValidateMethod(LambdaExpression methodCall, MethodInfo methodInfo)
11650
{
117-
this.TestContext.ComponentBuildDelegate?.Invoke();
118-
119-
this.TestContext.MethodCall = actionCall;
120-
this.TestContext.PreMethodInvocationDelegate?.Invoke();
121-
122-
var methodInfo = ExpressionParser.GetMethodInfo(actionCall);
51+
this.SetActionDescriptor(methodInfo);
12352

12453
if (this.EnabledModelStateValidation)
12554
{
126-
this.ValidateModelState(actionCall);
55+
this.ValidateModelState(methodCall);
12756
}
128-
129-
this.SetActionDescriptor(methodInfo);
130-
131-
return methodInfo.Name;
13257
}
13358

13459
private void ValidateModelState(LambdaExpression actionCall)

src/MyTested.AspNetCore.Mvc.Controllers/Builders/Controllers/ControllerBuilder.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
using Internal.Application;
66
using Internal.Contracts;
77
using Internal.TestContexts;
8+
using Microsoft.AspNetCore.Mvc.Controllers;
9+
using Microsoft.AspNetCore.Mvc.Internal;
810
using Microsoft.Extensions.DependencyInjection;
11+
using Utilities.Extensions;
912

1013
/// <summary>
1114
/// Used for building the controller which will be tested.
@@ -44,5 +47,26 @@ public IControllerTestBuilder ShouldHave()
4447
}
4548

4649
protected override IAndControllerBuilder<TController> SetBuilder() => this;
50+
51+
protected override TController TryCreateComponentWithFactory()
52+
{
53+
try
54+
{
55+
return this.Services
56+
.GetService<IControllerFactory>()
57+
?.CreateController(this.TestContext.ComponentContext) as TController;
58+
}
59+
catch
60+
{
61+
return null;
62+
}
63+
}
64+
65+
protected override void ActivateComponent()
66+
{
67+
this.Services
68+
.GetServices<IControllerPropertyActivator>()
69+
?.ForEach(a => a.Activate(this.TestContext.ComponentContext, this.TestContext.Component));
70+
}
4771
}
4872
}

0 commit comments

Comments
 (0)