Skip to content

Commit f316231

Browse files
authored
Merge pull request #203 from ivaylokenov/view-component-testing
Various enhancements and fixes
2 parents f6686bd + 76d3bc8 commit f316231

File tree

216 files changed

+2844
-1611
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

216 files changed

+2844
-1611
lines changed

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,9 @@ MyMvc
169169
.MemoryCache(cache => cache
170170
.ContainingEntry(entry => entry
171171
.WithKey("CacheEntry")
172-
.WithSlidingExpiration(TimeSpan.FromMinutes(10))))
172+
.WithSlidingExpiration(TimeSpan.FromMinutes(10))
173+
.WithValueOfType<CachedModel>()
174+
.Passing(a => a.Id == 1)))
173175
.AndAlso()
174176
.ShouldReturn()
175177
.View()
@@ -187,7 +189,8 @@ MyMvc
187189
.ChangingActionNameTo("AnotherAction"));
188190

189191
// tests whether model state error exists by using lambda expression
190-
// and specific tests for the error messages
192+
// and with specific tests for the error messages
193+
// and tests whether the action return view with the same request model
191194
MyMvc
192195
.Controller<MvcController>()
193196
.Calling(c => c.MyAction(requestWithErrors))
@@ -196,7 +199,10 @@ MyMvc
196199
.ContainingNoErrorFor(m => m.NonRequiredProperty)
197200
.AndAlso()
198201
.ContainingErrorFor(m => m.RequiredProperty)
199-
.ThatEquals("The RequiredProperty field is required."));
202+
.ThatEquals("The RequiredProperty field is required."))
203+
.AndAlso()
204+
.ShouldReturn()
205+
.View(requestWithErrors);
200206

201207
// tests whether the action throws
202208
// with exception of certain type and with certain message

samples/MusicStore/MusicStore.Test/Controllers/ShoppingCartControllerTest.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using MyTested.AspNetCore.Mvc;
88
using ViewModels;
99
using Xunit;
10+
using Microsoft.AspNetCore.Http;
1011

1112
public class ShoppingCartControllerTest
1213
{
@@ -89,8 +90,7 @@ public void AddToCartShouldAddItemsToCart()
8990
.Redirect()
9091
.To<ShoppingCartController>(c => c.Index())
9192
.AndAlso()
92-
.ShouldPassFor()
93-
.TheHttpContext(async httpContext =>
93+
.ShouldPassForThe<HttpContext>(async httpContext =>
9494
{
9595
var cart = ShoppingCart.GetCart(From.Services<MusicStoreContext>(), httpContext);
9696
Assert.Equal(1, (await cart.GetCartItems()).Count);
@@ -127,8 +127,7 @@ public void RemoveFromCartShouldRemoveItemFromCart()
127127
Assert.Equal(" has been removed from your shopping cart.", model.Message);
128128
})
129129
.AndAlso()
130-
.ShouldPassFor()
131-
.TheHttpContext(async httpContext =>
130+
.ShouldPassForThe<HttpContext>(async httpContext =>
132131
{
133132
var cart = ShoppingCart.GetCart(From.Services<MusicStoreContext>(), httpContext);
134133
Assert.False((await cart.GetCartItems()).Any(c => c.CartItemId == cartItemId));

samples/MusicStore/MusicStore.Test/Controllers/StoreControllerTest.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ public void DetailsShouldAlbumDetails()
9393
.MemoryCache(cache => cache
9494
.ContainingEntry(entry => entry
9595
.WithKey("album_1")
96-
.WithSlidingExpiration(TimeSpan.FromMinutes(10))))
96+
.WithSlidingExpiration(TimeSpan.FromMinutes(10))
97+
.WithValueOfType<Album>()
98+
.Passing(a => a.AlbumId == 1)))
9799
.AndAlso()
98100
.ShouldReturn()
99101
.View()

samples/MusicStore/MusicStore.Test/TestStartup.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ public void ConfigureTestServices(IServiceCollection services)
3636

3737
TestHelper.HttpFeatureRegistrationPlugins.Add(new SessionTestPlugin());
3838

39+
TestHelper.ShouldPassForPlugins.Add(new AbstractionsTestPlugin());
40+
TestHelper.ShouldPassForPlugins.Add(new ControllersTestPlugin());
41+
3942
services
4043
.AddMvcTesting()
4144
.AddRoutingTesting();
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
{
2-
"TestAssemblyName": "MusicStore.Test"
2+
"General": {
3+
"TestAssemblyName": "MusicStore.Test"
4+
}
35
}
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: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
namespace MyTested.AspNetCore.Mvc.Builders.Base
22
{
33
using Contracts.Base;
4-
using Contracts.ShouldPassFor;
54
using Internal.TestContexts;
65
using Licensing;
76
using Microsoft.AspNetCore.Http;
8-
using ShouldPassFor;
97
using Utilities.Validators;
108

119
/// <summary>
@@ -45,8 +43,5 @@ private set
4543
this.testContext = value;
4644
}
4745
}
48-
49-
/// <inheritdoc />
50-
public IShouldPassForTestBuilder ShouldPassFor() => new ShouldPassForTestBuilder(this.TestContext);
5146
}
5247
}

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

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
namespace MyTested.AspNetCore.Mvc.Builders.Base
22
{
33
using System;
4-
using System.Collections.Generic;
4+
using And;
5+
using Contracts.And;
56
using Contracts.Base;
7+
using Exceptions;
8+
using Internal;
69
using Internal.TestContexts;
10+
using Utilities;
711
using Utilities.Validators;
812

913
/// <summary>
@@ -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,32 @@ 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+
this.TestContext.ComponentBuildDelegate?.Invoke();
53+
54+
assertions(TestHelper.TryGetShouldPassForValue<TComponent>(this.TestContext));
55+
56+
return new AndTestBuilder(this.TestContext);
57+
}
58+
59+
/// <inheritdoc />
60+
public IAndTestBuilder ShouldPassForThe<TComponent>(Func<TComponent, bool> predicate)
61+
where TComponent : class
62+
{
63+
this.TestContext.ComponentBuildDelegate?.Invoke();
64+
65+
if (!predicate(TestHelper.TryGetShouldPassForValue<TComponent>(this.TestContext)))
66+
{
67+
throw new InvalidAssertionException($"Expected {typeof(TComponent).ToFriendlyTypeName()} to pass the given predicate but it failed.");
68+
}
69+
70+
return new AndTestBuilder(this.TestContext);
71+
}
72+
73+
protected IAndTestBuilder NewAndTestBuilder() => new AndTestBuilder(this.TestContext);
4374
}
4475
}
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 Base;
4+
using Contracts.Base;
5+
using Internal.TestContexts;
6+
7+
public abstract class BaseComponentBuilder<TBuilder> : BaseTestBuilderWithComponentBuilder<TBuilder>
8+
where TBuilder : IBaseTestBuilder
9+
{
10+
public BaseComponentBuilder(ComponentTestContext testContext)
11+
: base(testContext)
12+
{
13+
this.TestContext.ComponentBuildDelegate += this.BuildComponentIfNotExists;
14+
}
15+
16+
protected abstract void BuildComponentIfNotExists();
17+
}
18+
}
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+
}

0 commit comments

Comments
 (0)