Skip to content

Commit b10ec81

Browse files
committed
View component should return view implemented (#66)
1 parent 269920c commit b10ec81

File tree

32 files changed

+351
-266
lines changed

32 files changed

+351
-266
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
namespace MyTested.AspNetCore.Mvc.Builders.Base
2+
{
3+
using System;
4+
using Contracts.Base;
5+
using Contracts.Models;
6+
using Internal;
7+
using Internal.TestContexts;
8+
using Exceptions;
9+
using Models;
10+
using Utilities;
11+
12+
public abstract class BaseTestBuilderWithResponseModel : BaseTestBuilderWithActionContext, IBaseTestBuilderWithResponseModel
13+
{
14+
public BaseTestBuilderWithResponseModel(ActionTestContext testContext)
15+
: base(testContext)
16+
{
17+
}
18+
19+
/// <summary>
20+
/// Gets or sets the error message format for the response model assertions.
21+
/// </summary>
22+
/// <value>String value.</value>
23+
protected string ErrorMessageFormat { get; set; } = ExceptionMessageFormats.ResponseModel;
24+
25+
/// <summary>
26+
/// Gets or sets the error message format for the response model type assertions.
27+
/// </summary>
28+
/// <value>String value.</value>
29+
protected string OfTypeErrorMessageFormat { get; set; } = ExceptionMessageFormats.ResponseModelOfType;
30+
31+
/// <inheritdoc />
32+
public IAndModelDetailsTestBuilder<TModel> WithModelOfType<TModel>()
33+
{
34+
var actualResponseDataType = this.GetReturnType();
35+
var expectedResponseDataType = typeof(TModel);
36+
37+
var responseDataTypeIsAssignable = Reflection.AreAssignable(
38+
expectedResponseDataType,
39+
actualResponseDataType);
40+
41+
if (!responseDataTypeIsAssignable)
42+
{
43+
throw new ResponseModelAssertionException(string.Format(
44+
this.OfTypeErrorMessageFormat,
45+
this.TestContext.ExceptionMessagePrefix,
46+
typeof(TModel).ToFriendlyTypeName(),
47+
actualResponseDataType.ToFriendlyTypeName()));
48+
}
49+
50+
this.TestContext.Model = this.GetActualModel<TModel>();
51+
return new ModelDetailsTestBuilder<TModel>(this.TestContext);
52+
}
53+
54+
/// <inheritdoc />
55+
public IAndModelDetailsTestBuilder<TModel> WithModel<TModel>(TModel expectedModel)
56+
{
57+
this.WithModelOfType<TModel>();
58+
59+
var actualModel = this.GetActualModel<TModel>();
60+
if (Reflection.AreNotDeeplyEqual(expectedModel, actualModel))
61+
{
62+
throw new ResponseModelAssertionException(string.Format(
63+
this.ErrorMessageFormat,
64+
this.TestContext.ExceptionMessagePrefix,
65+
typeof(TModel).ToFriendlyTypeName()));
66+
}
67+
68+
this.TestContext.Model = actualModel;
69+
return new ModelDetailsTestBuilder<TModel>(this.TestContext);
70+
}
71+
72+
protected abstract TModel GetActualModel<TModel>();
73+
74+
protected abstract Type GetReturnType();
75+
}
76+
}
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@
55
/// <summary>
66
/// Base interface for all test builders with response model.
77
/// </summary>
8-
public interface IBaseTestBuilderWithResponseModel : IBaseTestBuilderWithInvokedAction
8+
public interface IBaseTestBuilderWithResponseModel : IBaseTestBuilderWithComponent
99
{
1010
/// <summary>
11-
/// Tests whether response model of the given type is returned from the invoked action.
11+
/// Tests whether response model of the given type is returned from the invoked method.
1212
/// </summary>
13-
/// <typeparam name="TResponseModel">Type of the response model.</typeparam>
13+
/// <typeparam name="TModel">Type of the response model.</typeparam>
1414
/// <returns>Test builder of <see cref="IModelDetailsTestBuilder{TResponseModel}"/>.</returns>
15-
IAndModelDetailsTestBuilder<TResponseModel> WithModelOfType<TResponseModel>();
15+
IAndModelDetailsTestBuilder<TModel> WithModelOfType<TModel>();
1616

1717
/// <summary>
18-
/// Tests whether a deeply equal object to the provided one is returned from the invoked action.
18+
/// Tests whether a deeply equal object to the provided one is returned from the invoked method.
1919
/// </summary>
20-
/// <typeparam name="TResponseModel">Type of the response model.</typeparam>
20+
/// <typeparam name="TModel">Type of the response model.</typeparam>
2121
/// <param name="expectedModel">Expected model to be returned.</param>
2222
/// <returns>Test builder of <see cref="IModelDetailsTestBuilder{TResponseModel}"/>.</returns>
23-
IAndModelDetailsTestBuilder<TResponseModel> WithModel<TResponseModel>(TResponseModel expectedModel);
23+
IAndModelDetailsTestBuilder<TModel> WithModel<TModel>(TModel expectedModel);
2424
}
2525
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
{
33
public class ExceptionMessageFormats
44
{
5+
public const string ResponseModel = "{0} response model {1} to be the given model, but in fact it was a different one.";
6+
public const string ResponseModelOfType = "{0} response model to be of {1} type, but instead received {2}.";
7+
58
public const string ContentResult = "{0} content result to contain '{1}', but instead received '{2}'.";
69
public const string ContentResultPredicate = "{0} content result ('{1}') to pass the given predicate, but it failed.";
710
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,5 +101,15 @@ public static TComponent TryGetShouldPassForValue<TComponent>(ComponentTestConte
101101
}
102102

103103
public static void ExecuteTestCleanup() => GlobalTestCleanup?.Invoke();
104+
105+
/// <summary>
106+
/// Gets formatted friendly name.
107+
/// </summary>
108+
/// <param name="name">Name to format.</param>
109+
/// <returns>Formatted string.</returns>
110+
public static string GetFriendlyName(string name)
111+
{
112+
return name == null ? "the default one" : $"'{name}'";
113+
}
104114
}
105115
}

src/MyTested.AspNetCore.Mvc.Abstractions/Utilities/Extensions/ObjectExtensions.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ public static T TryCastTo<T>(this object obj)
2323
}
2424
}
2525

26+
/// <summary>
27+
/// Returns the provided object casted as dynamic type.
28+
/// </summary>
29+
/// <returns>Object of dynamic type.</returns>
30+
public static dynamic AsDynamic(this object obj) => obj?.GetType().CastTo<dynamic>(obj);
31+
2632
/// <summary>
2733
/// Gets friendly type name of object. Useful for generic types.
2834
/// </summary>

src/MyTested.AspNetCore.Mvc.Caching/Builders/Data/MemoryCacheEntryTestBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class MemoryCacheEntryTestBuilder : MemoryCacheEntryBuilder, IMemoryCache
2323
/// <param name="testContext"><see cref="ComponentTestContext"/> containing data about the currently executed assertion chain.</param>
2424
public MemoryCacheEntryTestBuilder(ComponentTestContext testContext)
2525
{
26-
CommonValidator.CheckForNullReference(testContext, nameof(testContext));
26+
CommonValidator.CheckForNullReference(testContext, nameof(ComponentTestContext));
2727

2828
this.validations = new List<Action<ICacheEntry, ICacheEntry>>();
2929
this.TestContext = testContext;

src/MyTested.AspNetCore.Mvc.Controllers/Builders/ActionResults/BadRequest/BadRequestErrorMessageTestBuilder.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,19 @@
1010
/// Used for testing specific bad request text error messages.
1111
/// </summary>
1212
public class BadRequestErrorMessageTestBuilder
13-
: BaseTestBuilderWithInvokedAction, IBadRequestErrorMessageTestBuilder
13+
: BaseTestBuilderWithComponent, IBadRequestErrorMessageTestBuilder
1414
{
1515
private readonly string actualMessage;
1616
private readonly IAndBadRequestTestBuilder badRequestTestBuilder;
1717

1818
/// <summary>
1919
/// Initializes a new instance of the <see cref="BadRequestErrorMessageTestBuilder"/> class.
2020
/// </summary>
21-
/// <param name="testContext"><see cref="ControllerTestContext"/> containing data about the currently executed assertion chain.</param>
21+
/// <param name="testContext"><see cref="ComponentTestContext"/> containing data about the currently executed assertion chain.</param>
2222
/// <param name="actualMessage">Actual text error message received from bad request result.</param>
2323
/// <param name="badRequestTestBuilder">Bad request test builder.</param>
2424
public BadRequestErrorMessageTestBuilder(
25-
ControllerTestContext testContext,
25+
ComponentTestContext testContext,
2626
string actualMessage,
2727
IAndBadRequestTestBuilder badRequestTestBuilder)
2828
: base(testContext)
@@ -87,8 +87,8 @@ private void ThrowNewBadRequestResultAssertionException(string messageFormat, st
8787
{
8888
throw new BadRequestResultAssertionException(string.Format(
8989
messageFormat,
90-
this.ActionName,
91-
this.Controller.GetName(),
90+
this.TestContext.MethodName,
91+
this.TestContext.Component.GetName(),
9292
operation,
9393
this.actualMessage));
9494
}

src/MyTested.AspNetCore.Mvc.Controllers/Builders/ActionResults/BadRequest/BadRequestTestBuilder.cs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ public class BadRequestTestBuilder<THttpBadRequestResult>
2222
: BaseTestBuilderWithResponseModel<THttpBadRequestResult>, IAndBadRequestTestBuilder
2323
where THttpBadRequestResult : ActionResult
2424
{
25-
private const string ErrorMessage = "When calling {0} action in {1} expected bad request result error to be the given object, but in fact it was a different.";
26-
private const string OfTypeErrorMessage = "When calling {0} action in {1} expected bad request result error to be of {2} type, but instead received {3}.";
25+
private const string ErrorMessage = "{0} bad request result error to be the given object, but in fact it was a different.";
26+
private const string OfTypeErrorMessage = "{0} bad request result error to be of {1} type, but instead received {2}.";
2727

2828
/// <summary>
2929
/// Initializes a new instance of the <see cref="BadRequestTestBuilder{TBadRequestResult}"/> class.
@@ -35,7 +35,7 @@ public BadRequestTestBuilder(ControllerTestContext testContext)
3535
this.ErrorMessageFormat = ErrorMessage;
3636
this.OfTypeErrorMessageFormat = OfTypeErrorMessage;
3737
}
38-
38+
3939
/// <inheritdoc />
4040
public IAndModelDetailsTestBuilder<TError> WithError<TError>(TError error)
4141
{
@@ -51,13 +51,12 @@ public IAndModelDetailsTestBuilder<TError> WithErrorOfType<TError>()
5151
/// <inheritdoc />
5252
public IAndBadRequestTestBuilder WithNoError()
5353
{
54-
var actualResult = this.ActionResult as BadRequestResult;
54+
var actualResult = this.TestContext.MethodResult as BadRequestResult;
5555
if (actualResult == null)
5656
{
5757
throw new ResponseModelAssertionException(string.Format(
58-
"When calling {0} action in {1} expected bad request result to not have error message, but in fact such was found.",
59-
this.ActionName,
60-
this.Controller.GetName()));
58+
"{0} bad request result to not have error message, but in fact such was found.",
59+
this.TestContext.ExceptionMessagePrefix));
6160
}
6261

6362
return this;
@@ -183,9 +182,8 @@ public IAndBadRequestTestBuilder WithErrorMessage(Func<string, bool> predicate)
183182
if (!predicate(actualErrorMessage))
184183
{
185184
throw new BadRequestResultAssertionException(string.Format(
186-
"When calling {0} action in {1} expected bad request error message ('{2}') to pass the given predicate, but it failed.",
187-
this.ActionName,
188-
this.Controller.GetName(),
185+
"{0} bad request error message ('{2}') to pass the given predicate, but it failed.",
186+
this.TestContext.ExceptionMessagePrefix,
189187
actualErrorMessage));
190188
}
191189

@@ -194,19 +192,18 @@ public IAndBadRequestTestBuilder WithErrorMessage(Func<string, bool> predicate)
194192

195193
/// <inheritdoc />
196194
public IBadRequestTestBuilder AndAlso() => this;
197-
195+
198196
protected override void ThrowNewFailedValidationException(string propertyName, string expectedValue, string actualValue)
199197
=> this.ThrowNewHttpBadRequestResultAssertionException(propertyName, expectedValue, actualValue);
200-
198+
201199
public object GetBadRequestObjectResultValue()
202200
{
203-
var actualBadRequestResult = this.ActionResult as BadRequestObjectResult;
201+
var actualBadRequestResult = this.TestContext.MethodResult as BadRequestObjectResult;
204202
if (actualBadRequestResult == null)
205203
{
206204
throw new BadRequestResultAssertionException(string.Format(
207-
"When calling {0} action in {1} expected bad request result to contain error object, but it could not be found.",
208-
this.ActionName,
209-
this.Controller.GetName()));
205+
"{0} bad request result to contain error object, but it could not be found.",
206+
this.TestContext.ExceptionMessagePrefix));
210207
}
211208

212209
return actualBadRequestResult.Value;
@@ -265,9 +262,8 @@ private void ThrowNewHttpBadRequestResultAssertionExceptionWithMessage(string ex
265262
private void ThrowNewHttpBadRequestResultAssertionException(string propertyName, string expectedValue, string actualValue)
266263
{
267264
throw new BadRequestResultAssertionException(string.Format(
268-
"When calling {0} action in {1} expected bad request result {2} {3}, but {4}.",
269-
this.ActionName,
270-
this.Controller.GetName(),
265+
"{0} bad request result {1} {2}, but {3}.",
266+
this.TestContext.ExceptionMessagePrefix,
271267
propertyName,
272268
expectedValue,
273269
actualValue));

0 commit comments

Comments
 (0)