Last active
November 27, 2023 22:17
-
-
Save d1820/b4fffe65f26f86a8b1057949310b0d14 to your computer and use it in GitHub Desktop.
.Net Controller Unit Test Mock Builder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Security.Claims; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.AspNetCore.Mvc; | |
using Moq; | |
namespace Infrastructure.Testing.Builders | |
{ | |
public class BuilderResult : HttpContextBuilderResult | |
{ | |
public Mock<IUrlHelper> MockUrlHelper { get; set; } | |
public void Deconstruct(out Mock<HttpContext> mockContext, out Mock<ClaimsIdentity> mockClaimsIdentity, out Mock<HttpRequest> mockRequest, out Mock<HttpResponse> mockResponse) | |
{ | |
mockContext = MockContext; | |
mockClaimsIdentity = MockClaimsIdentity; | |
mockRequest = MockRequest; | |
mockResponse = MockResponse; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Security.Claims; | |
using Moq; | |
namespace Infrastructure.Testing.Builders | |
{ | |
public class ClaimsIdentityBuilder : IClaimsIdentityBuilder<ClaimsIdentityBuilder> | |
{ | |
private readonly Mock<ClaimsIdentity> _mockClaimsIdentity; | |
public ClaimsIdentityBuilder() | |
{ | |
_mockClaimsIdentity = new Mock<ClaimsIdentity>(); | |
} | |
public ClaimsIdentityBuilder WithUserAuthenticated(bool isAuthenticated = true) | |
{ | |
_mockClaimsIdentity.SetupGet(s => s.IsAuthenticated).Returns(isAuthenticated); | |
return this; | |
} | |
public ClaimsIdentityBuilder WithUserName(string name = "TestUser") | |
{ | |
_mockClaimsIdentity.SetupGet(s => s.Name).Returns(name); | |
return this; | |
} | |
public ClaimsIdentityBuilder WithUserClaims(List<Claim> claims = null) | |
{ | |
var claimList = new List<Claim> | |
{ | |
new Claim(ClaimTypes.NameIdentifier, "1"), | |
}; | |
if (claims != null) | |
{ | |
claimList.AddRange(claims); | |
} | |
_mockClaimsIdentity.SetupGet(s => s.Claims).Returns(claims); | |
return this; | |
} | |
public Mock<ClaimsIdentity> Build() | |
{ | |
return _mockClaimsIdentity; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Security.Claims; | |
using Moq; | |
namespace Infrastructure.Testing.Builders | |
{ | |
public class ClaimsIdentityBuilderResult | |
{ | |
public Mock<ClaimsIdentity> MockClaimsIdentity { get; set; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Security.Claims; | |
using Infrastructure.Testing.Mocks; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.AspNetCore.Mvc; | |
using Microsoft.AspNetCore.Mvc.Routing; | |
using Moq; | |
namespace Infrastructure.Testing.Builders | |
{ | |
public class ControllerBuilder : IHttpContextBuilder<ControllerBuilder, BuilderResult> | |
{ | |
private readonly Controller _controller; | |
private bool _hasContext; | |
private Mock<IUrlHelper> _urlHelperMock; | |
private readonly HttpContextBuilder _mockHttpContextBuilder; | |
public ControllerBuilder(Controller controller) | |
{ | |
_controller = controller; | |
_mockHttpContextBuilder = new HttpContextBuilder(); | |
} | |
public ControllerBuilder WithContext() | |
{ | |
_hasContext = true; | |
return this; | |
} | |
public ControllerBuilder WithRequest() | |
{ | |
_mockHttpContextBuilder.WithRequest(); | |
return this; | |
} | |
public ControllerBuilder WithContextItems(Dictionary<object, object> items) | |
{ | |
_mockHttpContextBuilder.WithContextItems(items); | |
return this; | |
} | |
public ControllerBuilder WithServiceProvider(Dictionary<Type, object> services) | |
{ | |
_mockHttpContextBuilder.WithServiceProvider(services); | |
return this; | |
} | |
public ControllerBuilder WithUrlHelper(string returnUrl = "www.google.com", | |
Action<UrlActionContext> callback = null, | |
Action<UrlRouteContext> routeCallback = null) | |
{ | |
_urlHelperMock = UrlHelperMock.Create(returnUrl, callback, routeCallback); | |
_controller.Url = _urlHelperMock.Object; | |
return this; | |
} | |
public ControllerBuilder WithResponse() | |
{ | |
_mockHttpContextBuilder.WithResponse(); | |
return this; | |
} | |
public ControllerBuilder WithUserAuthenticated(bool isAuthenticated = true) | |
{ | |
_mockHttpContextBuilder.WithUserAuthenticated(isAuthenticated); | |
return this; | |
} | |
public ControllerBuilder WithUserName(string name = "TestUser") | |
{ | |
_mockHttpContextBuilder.WithUserName(name); | |
return this; | |
} | |
public ControllerBuilder WithUserClaims(List<Claim> claims = null) | |
{ | |
_mockHttpContextBuilder.WithUserClaims(claims); | |
return this; | |
} | |
public ControllerBuilder WithCookies(Dictionary<string, string> cookies = null) | |
{ | |
_mockHttpContextBuilder.WithCookies(cookies); | |
return this; | |
} | |
public ControllerBuilder WithHeaders(HeaderDictionary headers) | |
{ | |
_mockHttpContextBuilder.WithHeaders(headers); | |
return this; | |
} | |
public ControllerBuilder WithResponseHeaders(HeaderDictionary headers) | |
{ | |
_mockHttpContextBuilder.WithResponseHeaders(headers); | |
return this; | |
} | |
public ControllerBuilder WithResponseCookies() | |
{ | |
_mockHttpContextBuilder.WithResponseCookies(); | |
return this; | |
} | |
public BuilderResult Build() | |
{ | |
var builderResult = _mockHttpContextBuilder.Build(); | |
if (_hasContext) | |
{ | |
_controller.ControllerContext = new ControllerContext { HttpContext = builderResult.MockContext.Object }; | |
} | |
return new BuilderResult | |
{ | |
MockContext = builderResult.MockContext, | |
MockClaimsIdentity = builderResult.MockClaimsIdentity, | |
MockRequest = builderResult.MockRequest, | |
MockResponse = builderResult.MockResponse, | |
MockUrlHelper = _urlHelperMock | |
}; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public ControllerTests() | |
{ | |
_pController = new PController(); | |
new ControllerBuilder(_pController).WithContext().WithRequest().WithResponse().WithResponseHeaders(new HeaderDictionary()).WithUrlHelper().Build(); | |
} | |
[Fact] | |
public void TestUsingMockedController() | |
{ | |
// Act | |
var result = _pController.Get(); | |
//Assert | |
result.Should().BeOfType<BadRequestObjectResult>(); | |
} | |
[Fact] | |
public async Task TestWithMockHttpContext() | |
{ | |
var headers = new HeaderDictionary | |
{ | |
new KeyValuePair<string, StringValues>(_key, _value) | |
}; | |
var builder = new HttpContextBuilder().WithRequest().WithCookies().WithHeaders(headers).Build(); | |
// Act | |
var Result = await class.methodThatNeedsAMockedHttpContext(builder.MockRequest.Object); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Security.Claims; | |
using Microsoft.AspNetCore.Http; | |
using Microsoft.AspNetCore.Http.Internal; | |
using Microsoft.AspNetCore.Mvc; | |
using Moq; | |
using HttpContext = Microsoft.AspNetCore.Http.HttpContext; | |
using HttpRequest = Microsoft.AspNetCore.Http.HttpRequest; | |
using HttpResponse = Microsoft.AspNetCore.Http.HttpResponse; | |
namespace Infrastructure.Testing.Builders | |
{ | |
public class HttpContextBuilder : IHttpContextBuilder<HttpContextBuilder, HttpContextBuilderResult> | |
{ | |
private readonly Mock<HttpContext> _mockContext; | |
private bool _hasUser; | |
private Mock<HttpRequest> _httpRequestMock; | |
private Mock<HttpResponse> _httpResponseMock; | |
private readonly ClaimsIdentityBuilder _mockClaimsIdentityBuilder; | |
private Mock<IResponseCookies> _mockResponseCookiesCollection; | |
public HttpContextBuilder() | |
{ | |
_mockContext = new Mock<HttpContext>(); | |
_mockClaimsIdentityBuilder = new ClaimsIdentityBuilder(); | |
} | |
public HttpContextBuilder WithRequest() | |
{ | |
_httpRequestMock = new Mock<HttpRequest>(MockBehavior.Strict); | |
_mockContext.SetupGet(s => s.Request).Returns(_httpRequestMock.Object); | |
return this; | |
} | |
public HttpContextBuilder WithContextItems(Dictionary<object, object> items) | |
{ | |
_mockContext.SetupGet(s => s.Items).Returns(items); | |
return this; | |
} | |
public HttpContextBuilder WithResponse() | |
{ | |
_httpResponseMock = new Mock<HttpResponse>(MockBehavior.Strict); | |
_mockContext.SetupGet(s => s.Response).Returns(_httpResponseMock.Object); | |
return this; | |
} | |
public HttpContextBuilder WithServiceProvider(Dictionary<Type, object> services) | |
{ | |
var serviceProviderMock = new Mock<IServiceProvider>(); | |
foreach (var service in services) | |
{ | |
serviceProviderMock.Setup(provider => provider.GetService(service.Key)) | |
.Returns(service.Value); | |
} | |
// Mock the HttpContext to return a mockable | |
_mockContext.SetupGet(context => context.RequestServices) | |
.Returns(serviceProviderMock.Object); | |
return this; | |
} | |
public HttpContextBuilder WithUserAuthenticated(bool isAuthenticated = true) | |
{ | |
_hasUser = true; | |
_mockClaimsIdentityBuilder.WithUserAuthenticated(isAuthenticated); | |
return this; | |
} | |
public HttpContextBuilder WithUserName(string name = "TestUser") | |
{ | |
_hasUser = true; | |
_mockClaimsIdentityBuilder.WithUserName(name); | |
return this; | |
} | |
public HttpContextBuilder WithUserClaims(List<Claim> claims = null) | |
{ | |
_hasUser = true; | |
_mockClaimsIdentityBuilder.WithUserClaims(claims); | |
return this; | |
} | |
public HttpContextBuilder WithCookies(Dictionary<string, string> cookies = null) | |
{ | |
if (_httpRequestMock == null) | |
{ | |
throw new Exception("WithRequest must be called first"); | |
} | |
if (cookies == null) | |
{ | |
cookies = new Dictionary<string, string>(); | |
} | |
var cc = new RequestCookieCollection(cookies); | |
_httpRequestMock.SetupGet(s => s.Cookies).Returns(cc); | |
return this; | |
} | |
public HttpContextBuilder WithHeaders(HeaderDictionary headers) | |
{ | |
if (_httpRequestMock == null) | |
{ | |
throw new Exception("WithRequest must be called first"); | |
} | |
_httpRequestMock.SetupGet(s => s.Headers).Returns(headers); | |
return this; | |
} | |
public HttpContextBuilder WithResponseHeaders(HeaderDictionary headers) | |
{ | |
if (_httpResponseMock == null) | |
{ | |
throw new Exception("WithResponse must be called first"); | |
} | |
_httpResponseMock.SetupGet(s => s.Headers).Returns(headers); | |
return this; | |
} | |
public HttpContextBuilder WithResponseCookies() | |
{ | |
if (_httpResponseMock == null) | |
{ | |
throw new Exception("WithResponse must be called first"); | |
} | |
// var rc = new ResponseCookies(new HeaderDictionary(cookies), new DefaultObjectPool<StringBuilder>(new StringBuilderPooledObjectPolicy())); | |
// | |
_mockResponseCookiesCollection = new Mock<IResponseCookies>(); | |
_httpResponseMock.SetupGet(s => s.Cookies).Returns(_mockResponseCookiesCollection.Object); | |
return this; | |
} | |
public HttpContextBuilderResult Build() | |
{ | |
var mockClaimsIdentity = _mockClaimsIdentityBuilder.Build(); | |
var user = new ClaimsPrincipal(mockClaimsIdentity.Object); | |
if (_hasUser) | |
{ | |
_mockContext.SetupGet(s => s.User).Returns(user); | |
} | |
return new HttpContextBuilderResult | |
{ | |
MockContext = _mockContext, | |
MockClaimsIdentity = mockClaimsIdentity, | |
MockRequest = _httpRequestMock, | |
MockResponse = _httpResponseMock, | |
MockResponseCookies = _mockResponseCookiesCollection | |
}; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.AspNetCore.Http; | |
using Moq; | |
namespace Infrastructure.Testing.Builders | |
{ | |
public class HttpContextBuilderResult : ClaimsIdentityBuilderResult | |
{ | |
public Mock<HttpContext> MockContext { get; set; } | |
public Mock<HttpRequest> MockRequest { get; set; } | |
public Mock<HttpResponse> MockResponse { get; set; } | |
public Mock<IResponseCookies> MockResponseCookies { get; set; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Security.Claims; | |
using Moq; | |
namespace Infrastructure.Testing.Builders | |
{ | |
public interface IClaimsIdentityBuilder<out TBuilder> | |
{ | |
TBuilder WithUserAuthenticated(bool isAuthenticated = true); | |
TBuilder WithUserClaims(List<Claim> claims = null); | |
TBuilder WithUserName(string name = "TestUser"); | |
} | |
} | |
using System; | |
using System.Collections.Generic; | |
using Microsoft.AspNetCore.Http; | |
namespace Infrastructure.Testing.Builders | |
{ | |
public interface IHttpContextBuilder<out TBuilder, out TResult>: IClaimsIdentityBuilder<TBuilder> | |
{ | |
TBuilder WithRequest(); | |
TBuilder WithResponse(); | |
TBuilder WithContextItems(Dictionary<object, object> items); | |
TBuilder WithServiceProvider(Dictionary<Type, object> services); | |
TBuilder WithCookies(Dictionary<string, string> cookies = null); | |
TBuilder WithHeaders(HeaderDictionary headers); | |
TBuilder WithResponseHeaders(HeaderDictionary headers); | |
TBuilder WithResponseCookies(); | |
TResult Build(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using Microsoft.AspNetCore.Mvc; | |
using Microsoft.AspNetCore.Mvc.Routing; | |
using Moq; | |
namespace Infrastructure.Testing.Mocks | |
{ | |
public static class UrlHelperMock | |
{ | |
public static Mock<IUrlHelper> Create(string returnUrl, | |
Action<UrlActionContext> callback = null, | |
Action<UrlRouteContext> routeCallback = null) | |
{ | |
var urlHelperMock = new Mock<IUrlHelper>(); | |
urlHelperMock.Setup( | |
x => x.Action( | |
It.IsAny<UrlActionContext>() | |
) | |
) | |
.Callback((UrlActionContext context) => | |
{ | |
callback?.Invoke(context); | |
}) | |
.Returns(returnUrl) | |
.Verifiable(); | |
urlHelperMock.Setup( | |
x => x.RouteUrl( | |
It.IsAny<UrlRouteContext>() | |
) | |
) | |
.Callback((UrlRouteContext context) => | |
{ | |
routeCallback?.Invoke(context); | |
}) | |
.Returns(returnUrl) | |
.Verifiable(); | |
return urlHelperMock; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment