Skip to content

Instantly share code, notes, and snippets.

@d1820
Last active November 27, 2023 22:17
Show Gist options
  • Save d1820/b4fffe65f26f86a8b1057949310b0d14 to your computer and use it in GitHub Desktop.
Save d1820/b4fffe65f26f86a8b1057949310b0d14 to your computer and use it in GitHub Desktop.
.Net Controller Unit Test Mock Builder
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;
}
}
}
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;
}
}
}
using System.Security.Claims;
using Moq;
namespace Infrastructure.Testing.Builders
{
public class ClaimsIdentityBuilderResult
{
public Mock<ClaimsIdentity> MockClaimsIdentity { get; set; }
}
}
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
};
}
}
}
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);
}
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
};
}
}
}
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; }
}
}
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();
}
}
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