Skip to content

Commit b620d86

Browse files
authored
Merge pull request #328 - Allow controller instance creation to be with inner builder
Allow controller instance creation to be with inner builder
2 parents 60218c2 + 11ade55 commit b620d86

File tree

14 files changed

+292
-125
lines changed

14 files changed

+292
-125
lines changed

samples/Blog/Blog.Test/Controllers/ArticlesControllerTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public class ArticlesControllerTest
2020
[InlineData(18, 2, 6)]
2121
public void AllShouldReturnDefaultViewWithCorrectModel(int total, int page, int expectedCount)
2222
=> MyController<ArticlesController>
23-
.Instance()
24-
.WithData(ArticleTestData.GetArticles(total))
23+
.Instance(instance => instance
24+
.WithData(ArticleTestData.GetArticles(total)))
2525
.Calling(c => c.All(page))
2626
.ShouldReturn()
2727
.View(view => view
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.Controllers
2+
{
3+
/// <summary>
4+
/// Used for adding AndAlso() method to the controller instance builder.
5+
/// </summary>
6+
/// <typeparam name="TController">Class representing ASP.NET Core MVC controller.</typeparam>
7+
public interface IAndControllerInstanceBuilder<TController> : IControllerInstanceBuilder<TController>
8+
where TController : class
9+
{
10+
/// <summary>
11+
/// AndAlso method for better readability when building controller instance.
12+
/// </summary>
13+
/// <returns>The same <see cref="IAndControllerBuilder{TController}"/>.</returns>
14+
IAndControllerInstanceBuilder<TController> AndAlso();
15+
}
16+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Controllers
2+
{
3+
using System;
4+
using Builders.Contracts.Base;
5+
using Microsoft.AspNetCore.Mvc;
6+
7+
/// <summary>
8+
/// Base controller builder.
9+
/// </summary>
10+
/// <typeparam name="TController">Class representing ASP.NET Core MVC controller.</typeparam>
11+
/// <typeparam name="TBuilder">Base builder.</typeparam>
12+
public interface IBaseControllerBuilder<TController, TBuilder> : IBaseTestBuilderWithComponentBuilder<TBuilder>
13+
where TController : class
14+
where TBuilder : IBaseTestBuilder
15+
{
16+
/// <summary>
17+
/// Sets the <see cref="ControllerContext"/> on the tested controller.
18+
/// </summary>
19+
/// <param name="controllerContext">Instance of <see cref="ControllerContext"/> to set.</param>
20+
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
21+
TBuilder WithControllerContext(ControllerContext controllerContext);
22+
23+
/// <summary>
24+
/// Sets the <see cref="ControllerContext"/> on the tested controller.
25+
/// </summary>
26+
/// <param name="controllerContextSetup">Action setting the <see cref="ControllerContext"/>.</param>
27+
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
28+
TBuilder WithControllerContext(Action<ControllerContext> controllerContextSetup);
29+
30+
/// <summary>
31+
/// Sets the <see cref="ActionContext"/> on the tested controller.
32+
/// </summary>
33+
/// <param name="actionContext">Instance of <see cref="ActionContext"/> to set.</param>
34+
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
35+
TBuilder WithActionContext(ActionContext actionContext);
36+
37+
/// <summary>
38+
/// Sets the <see cref="ActionContext"/> on the tested controller.
39+
/// </summary>
40+
/// <param name="actionContextSetup">Action setting the <see cref="ActionContext"/>.</param>
41+
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
42+
TBuilder WithActionContext(Action<ActionContext> actionContextSetup);
43+
44+
/// <summary>
45+
/// Sets custom properties to the controller using a delegate.
46+
/// </summary>
47+
/// <param name="controllerSetup">Action to use for controller setup.</param>
48+
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
49+
TBuilder WithSetup(Action<TController> controllerSetup);
50+
}
51+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Controllers
2+
{
3+
using System;
4+
using System.Linq.Expressions;
5+
using System.Threading.Tasks;
6+
using Actions;
7+
using Base;
8+
9+
/// <summary>
10+
/// Used for testing the controller.
11+
/// </summary>
12+
/// <typeparam name="TController">Class representing ASP.NET Core MVC controller.</typeparam>
13+
public interface IControllerActionCallBuilder<TController> : IBaseTestBuilderWithComponent
14+
{
15+
/// <summary>
16+
/// Used for testing controller additional details.
17+
/// </summary>
18+
/// <returns>Test builder of <see cref="IControllerTestBuilder"/> type.</returns>
19+
IControllerTestBuilder ShouldHave();
20+
21+
/// <summary>
22+
/// Indicates which action should be invoked and tested.
23+
/// </summary>
24+
/// <typeparam name="TActionResult">Type of result from action.</typeparam>
25+
/// <param name="actionCall">Method call expression indicating invoked action.</param>
26+
/// <returns>Test builder of <see cref="IActionResultTestBuilder{TActionResult}"/> type.</returns>
27+
IActionResultTestBuilder<TActionResult> Calling<TActionResult>(Expression<Func<TController, TActionResult>> actionCall);
28+
29+
/// <summary>
30+
/// Indicates which action should be invoked and tested.
31+
/// </summary>
32+
/// <typeparam name="TActionResult">Type of result from action.</typeparam>
33+
/// <param name="actionCall">Method call expression indicating invoked asynchronous action.</param>
34+
/// <returns>Test builder of <see cref="IActionResultTestBuilder{TActionResult}"/> type.</returns>
35+
IActionResultTestBuilder<TActionResult> Calling<TActionResult>(Expression<Func<TController, Task<TActionResult>>> actionCall);
36+
37+
/// <summary>
38+
/// Indicates which action should be invoked and tested.
39+
/// </summary>
40+
/// <param name="actionCall">Method call expression indicating invoked void action.</param>
41+
/// <returns>Test builder of <see cref="IActionResultTestBuilder{TActionResult}"/> type.</returns>
42+
IVoidActionResultTestBuilder Calling(Expression<Action<TController>> actionCall);
43+
44+
/// <summary>
45+
/// Indicates which action should be invoked and tested.
46+
/// </summary>
47+
/// <param name="actionCall">Method call expression indicating invoked asynchronous void action.</param>
48+
/// <returns>Test builder of <see cref="IActionResultTestBuilder{TActionResult}"/> type.</returns>
49+
IVoidActionResultTestBuilder Calling(Expression<Func<TController, Task>> actionCall);
50+
}
51+
}
Lines changed: 3 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,13 @@
11
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Controllers
22
{
3-
using System;
4-
using System.Linq.Expressions;
5-
using System.Threading.Tasks;
6-
using Actions;
7-
using Base;
8-
using Microsoft.AspNetCore.Mvc;
9-
103
/// <summary>
114
/// Used for building the controller which will be tested.
125
/// </summary>
136
/// <typeparam name="TController">Class representing ASP.NET Core MVC controller.</typeparam>
14-
public interface IControllerBuilder<TController> : IBaseTestBuilderWithComponentBuilder<IAndControllerBuilder<TController>>
7+
public interface IControllerBuilder<TController>
8+
: IBaseControllerBuilder<TController, IAndControllerBuilder<TController>>,
9+
IControllerActionCallBuilder<TController>
1510
where TController : class
1611
{
17-
/// <summary>
18-
/// Used for testing controller additional details.
19-
/// </summary>
20-
/// <returns>Test builder of <see cref="IControllerTestBuilder"/> type.</returns>
21-
IControllerTestBuilder ShouldHave();
22-
23-
/// <summary>
24-
/// Sets the <see cref="ControllerContext"/> on the tested controller.
25-
/// </summary>
26-
/// <param name="controllerContext">Instance of <see cref="ControllerContext"/> to set.</param>
27-
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
28-
IAndControllerBuilder<TController> WithControllerContext(ControllerContext controllerContext);
29-
30-
/// <summary>
31-
/// Sets the <see cref="ControllerContext"/> on the tested controller.
32-
/// </summary>
33-
/// <param name="controllerContextSetup">Action setting the <see cref="ControllerContext"/>.</param>
34-
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
35-
IAndControllerBuilder<TController> WithControllerContext(Action<ControllerContext> controllerContextSetup);
36-
37-
/// <summary>
38-
/// Sets the <see cref="ActionContext"/> on the tested controller.
39-
/// </summary>
40-
/// <param name="actionContext">Instance of <see cref="ActionContext"/> to set.</param>
41-
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
42-
IAndControllerBuilder<TController> WithActionContext(ActionContext actionContext);
43-
44-
/// <summary>
45-
/// Sets the <see cref="ActionContext"/> on the tested controller.
46-
/// </summary>
47-
/// <param name="actionContextSetup">Action setting the <see cref="ActionContext"/>.</param>
48-
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
49-
IAndControllerBuilder<TController> WithActionContext(Action<ActionContext> actionContextSetup);
50-
51-
/// <summary>
52-
/// Sets custom properties to the controller using a delegate.
53-
/// </summary>
54-
/// <param name="controllerSetup">Action to use for controller setup.</param>
55-
/// <returns>The same <see cref="IControllerBuilder{TController}"/>.</returns>
56-
IAndControllerBuilder<TController> WithSetup(Action<TController> controllerSetup);
57-
58-
/// <summary>
59-
/// Indicates which action should be invoked and tested.
60-
/// </summary>
61-
/// <typeparam name="TActionResult">Type of result from action.</typeparam>
62-
/// <param name="actionCall">Method call expression indicating invoked action.</param>
63-
/// <returns>Test builder of <see cref="IActionResultTestBuilder{TActionResult}"/> type.</returns>
64-
IActionResultTestBuilder<TActionResult> Calling<TActionResult>(Expression<Func<TController, TActionResult>> actionCall);
65-
66-
/// <summary>
67-
/// Indicates which action should be invoked and tested.
68-
/// </summary>
69-
/// <typeparam name="TActionResult">Type of result from action.</typeparam>
70-
/// <param name="actionCall">Method call expression indicating invoked asynchronous action.</param>
71-
/// <returns>Test builder of <see cref="IActionResultTestBuilder{TActionResult}"/> type.</returns>
72-
IActionResultTestBuilder<TActionResult> Calling<TActionResult>(Expression<Func<TController, Task<TActionResult>>> actionCall);
73-
74-
/// <summary>
75-
/// Indicates which action should be invoked and tested.
76-
/// </summary>
77-
/// <param name="actionCall">Method call expression indicating invoked void action.</param>
78-
/// <returns>Test builder of <see cref="IActionResultTestBuilder{TActionResult}"/> type.</returns>
79-
IVoidActionResultTestBuilder Calling(Expression<Action<TController>> actionCall);
80-
81-
/// <summary>
82-
/// Indicates which action should be invoked and tested.
83-
/// </summary>
84-
/// <param name="actionCall">Method call expression indicating invoked asynchronous void action.</param>
85-
/// <returns>Test builder of <see cref="IActionResultTestBuilder{TActionResult}"/> type.</returns>
86-
IVoidActionResultTestBuilder Calling(Expression<Func<TController, Task>> actionCall);
8712
}
8813
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Contracts.Controllers
2+
{
3+
/// <summary>
4+
/// Used for building the controller which will be tested.
5+
/// </summary>
6+
/// <typeparam name="TController">Class representing ASP.NET Core MVC controller.</typeparam>
7+
public interface IControllerInstanceBuilder<TController> : IBaseControllerBuilder<TController, IAndControllerInstanceBuilder<TController>>
8+
where TController : class
9+
{
10+
}
11+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Controllers
2+
{
3+
using Components;
4+
using Contracts.Base;
5+
using Internal.Contracts;
6+
using Internal.TestContexts;
7+
using Microsoft.AspNetCore.Mvc.Controllers;
8+
using Microsoft.AspNetCore.Mvc.Internal;
9+
using Microsoft.Extensions.DependencyInjection;
10+
using System.Linq.Expressions;
11+
using System.Reflection;
12+
using Utilities.Extensions;
13+
14+
/// <summary>
15+
/// Base controller builder.
16+
/// </summary>
17+
/// /// <typeparam name="TController">Class representing ASP.NET Core MVC controller.</typeparam>
18+
/// <typeparam name="TBuilder">Base builder.</typeparam>
19+
public abstract partial class BaseControllerBuilder<TController, TBuilder>
20+
: BaseComponentBuilder<TController, ControllerTestContext, TBuilder>
21+
where TController : class
22+
where TBuilder : IBaseTestBuilder
23+
{
24+
/// <summary>
25+
/// Initializes a new instance of the <see cref="BaseControllerBuilder{TController, TBuilder}"/> class.
26+
/// </summary>
27+
/// <param name="testContext"><see cref="ControllerTestContext"/> containing data about the currently executed assertion chain.</param>
28+
protected BaseControllerBuilder(ControllerTestContext testContext)
29+
: base(testContext)
30+
{
31+
}
32+
33+
protected override string ComponentName => "controller";
34+
35+
protected override bool IsValidComponent
36+
=> this.Services
37+
.GetRequiredService<IValidControllersCache>()
38+
.IsValid(typeof(TController));
39+
40+
protected override TController TryCreateComponentWithFactory()
41+
{
42+
try
43+
{
44+
return this.Services
45+
.GetService<IControllerFactory>()
46+
?.CreateController(this.TestContext.ComponentContext) as TController;
47+
}
48+
catch
49+
{
50+
return null;
51+
}
52+
}
53+
54+
protected override void ActivateComponent()
55+
=> this.Services
56+
.GetServices<IControllerPropertyActivator>()
57+
?.ForEach(a => a.Activate(this.TestContext.ComponentContext, this.TestContext.Component));
58+
59+
protected override void ProcessAndValidateMethod(LambdaExpression methodCall, MethodInfo methodInfo)
60+
{
61+
// Intentionally left empty. Not all controller builders allow action execution.
62+
}
63+
}
64+
}

src/MyTested.AspNetCore.Mvc.Controllers/Builders/Controllers/ControllerSetupBuilder.cs renamed to src/MyTested.AspNetCore.Mvc.Controllers/Builders/Controllers/BaseControllerSetupBuilder.cs

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,39 @@
22
{
33
using System;
44
using System.Reflection;
5-
using Contracts.Controllers;
65
using Internal.Controllers;
76
using Microsoft.AspNetCore.Mvc;
87
using Utilities.Validators;
98

109
/// <content>
1110
/// Used for building the controller which will be tested.
1211
/// </content>
13-
public partial class ControllerBuilder<TController>
12+
public abstract partial class BaseControllerBuilder<TController, TBuilder>
1413
{
1514
/// <inheritdoc />
16-
public IAndControllerBuilder<TController> WithControllerContext(ControllerContext controllerContext)
17-
{
18-
return this.WithActionContext(controllerContext);
19-
}
15+
public TBuilder WithControllerContext(ControllerContext controllerContext)
16+
=> this.WithActionContext(controllerContext);
2017

2118
/// <inheritdoc />
22-
public IAndControllerBuilder<TController> WithControllerContext(Action<ControllerContext> controllerContextSetup)
19+
public TBuilder WithControllerContext(Action<ControllerContext> controllerContextSetup)
2320
{
2421
this.TestContext.ComponentContextPreparationDelegate += controllerContextSetup;
25-
return this;
22+
return this.Builder;
2623
}
2724

2825
/// <inheritdoc />
29-
public IAndControllerBuilder<TController> WithActionContext(ActionContext actionContext)
26+
public TBuilder WithActionContext(ActionContext actionContext)
3027
{
3128
CommonValidator.CheckForNullReference(actionContext, nameof(ActionContext));
3229
this.TestContext.ComponentContext = ControllerContextMock.FromActionContext(this.TestContext, actionContext);
33-
return this;
30+
return this.Builder;
3431
}
3532

3633
/// <inheritdoc />
37-
public IAndControllerBuilder<TController> WithActionContext(Action<ActionContext> actionContextSetup)
34+
public TBuilder WithActionContext(Action<ActionContext> actionContextSetup)
3835
{
3936
this.TestContext.ComponentContextPreparationDelegate += actionContextSetup;
40-
return this;
37+
return this.Builder;
4138
}
4239

4340
protected override void PrepareComponentContext()

0 commit comments

Comments
 (0)