xUnit ClaimsPrincipal mock and passing into controller User is null - unit-testing

I have been reading articles trying to figure this one out. Structured off of this article How to add claims in a mock ClaimsPrincipal. I am still getting a null user from my controller and test fails on a null object of User inside the controller.
BusinessController
[Route("api/[controller]")]
[ApiController]
public class BusinessController : ControllerBase
{
private readonly IGBusinessRepository businessRepository;
private readonly IPersonRepository personRepository;
private readonly IUserClaims userClaims;
public BusinessController(IGBusinessRepository businessRepository,
IPersonRepository personRepository,
IUserClaims userClaims)
{
this.businessRepository = businessRepository;
this.personRepository = personRepository;
this.userClaims = userClaims;
}
// GET api/<BusinessController>/5
[HttpGet("{id}")]
[Authorize]
public async Task<IActionResult> GetBusiness(Guid businessId)
{
var userGuid = userClaims.GetUserGuid(User.Claims);
var ownerId = await personRepository.GetPersonIdByGUID(userGuid);
var business = await businessRepository.GetBusinessById(businessId);
if(business != null && business.OwnerId == businessId)
{
return Ok(business);
}
return BadRequest("Bad business id or your not the owner");
}
UserClaims
public class UserClaims : IUserClaims
{
public string GetUserGuid(IEnumerable<Claim> claims)
{
var claimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
var guidClaim = claims.Where(c => c.Type == claimType).Select(s => s.Value).SingleOrDefault();
return guidClaim;
}
}
TestIdentity
public class TestIdentity : ClaimsIdentity
{
public TestIdentity(params Claim[] claims) : base(claims)
{
}
}
TestPrincipal
public class TestPrincipal : ClaimsPrincipal
{
public TestPrincipal(params Claim[] claims) : base(new TestIdentity(claims))
{
}
}
BusinessControllerTests
public class BusinessControllerTests
{
//Controller
private readonly Mock<IGBusinessRepository> mockBusinessRepository;
private readonly Mock<IPersonRepository> mockPersonRepository;
private readonly Mock<IUserClaims> mockUserClaims;
private BusinessController controller;
//Objects
private Guid id = Guid.NewGuid();
public BusinessControllerTests()
{
mockBusinessRepository = new Mock<IGBusinessRepository>();
mockPersonRepository = new Mock<IPersonRepository>();
mockUserClaims = new Mock<IUserClaims>();
controller = new BusinessController(mockBusinessRepository.Object, mockPersonRepository.Object, mockUserClaims.Object);
}
[Fact]
public async Task GetBussiness_NotBusinessOwner_ReturnsBadRequest()
{
//Arrange
var userGuidString = Guid.NewGuid().ToString();
var ownerId = Guid.NewGuid();
var userClaim = new TestPrincipal(new Claim("name", "user#domain.com"));
Thread.CurrentPrincipal = userClaim;
//mockUserClaims.Setup(repo => repo.GetUserGuid(userClaim)).Returns(userGuidString);
mockPersonRepository.Setup(repo => repo.GetPersonIdByGUID(userGuidString));
mockBusinessRepository.Setup(repo => repo.GetBusinessById(id)).ReturnsAsync(business);
//Act
var result = await controller.GetBusiness(id);
//Assert
Assert.IsType<BadRequestResult>(result);
}
private GobiezBusiness business = new GobiezBusiness()
{
Id = new MongoDB.Bson.ObjectId(),
BusinessId = Guid.NewGuid(),
Name = "Test",
Email = "Test#helpme.com",
Address = "123 A street",
State = "WA",
ZipCode = "12345",
PhoneNumber = "123-456-7890",
OwnerId = Guid.NewGuid()
};
}

The controller was not arranged correctly to be able to access the principal
// ... omitted for brevity
var userClaim = new TestPrincipal(new Claim("name", "user#domain.com"));
var httpContext = new DefaultHttpContext() {
User = userClaim;
};
//Controller needs a controller context to access HttpContext
var controllerContext = new ControllerContext() {
HttpContext = httpContext
};
//assign context to controller
BusinessController controller = new BusinessController(
mockBusinessRepository.Object,
mockPersonRepository.Object,
mockUserClaims.Object)
{
ControllerContext = controllerContext
};
//Act
var result = await controller.GetBusiness(id);
// ... omitted for brevity
The controller should also be created within the scope of the test being executed.
This line in the subject under test
//...
var userGuid = userClaims.GetUserGuid(User.Claims);
//...
Should now return the created TestPrincipal arranged in the test

Related

unit test for MediatR in .net6 with generic repo returns null repository

I am using MediatR for command query segregation.
I want to test the command method, my command method accept a clientappsetting model as an input .here you can see my whole handler and command code :
AddClientAppSettingCommandHandler : IRequestHandler<AddClientAppSettingCommand, AddClientAppSettingResponse>
{
private readonly ICurrentUserService _userService;
private readonly IRepository<ClientAppSettings> _repository;
public AddClientAppSettingCommandHandler(ICurrentUserService userService,
IRepositoryAccessor repositoryAccessor)
{
_userService = userService;
_repository = repositoryAccessor.GetRepository<ClientAppSettings>(_userService.CustomerIsin,
reThrowException: true, type: DatabaseType.Raven);
}
public async Task<AddClientAppSettingResponse> Handle(AddClientAppSettingCommand request,
CancellationToken cancellationToken)
{
var entity = new ClientAppSettings(_userService.CustomerIsin)
{
LightTheme = request.Setting.LightTheme,
Order = request.Setting.Order,
Notch = request.Setting.Notch,
PageSize = request.Setting.PageSize,
ApplyCommissionInPortfolio = request.Setting.ApplyCommissionInPortfolio,
UseClosingPriceInPortfolioTotalValue = request.Setting.UseClosingPriceInPortfolioTotalValue,
ShowNotifications = request.Setting.ShowNotifications,
NoSleep = request.Setting.NoSleep,
NoBalance = request.Setting.NoBalance,
DataTracker = request.Setting.DataTracker,
UserStatusBarToUp = request.Setting.UserStatusBarToUp,
PortfolioBasedOnLastPositivePeriod = request.Setting.PortfolioBasedOnLastPositivePeriod,
};
var cRepository = CacheableRepository<ClientAppSettings>.From(_repository);
var result = await cRepository.AddOrUpdateAsync(entity);
if (!result.IsSucceeded)
throw new EasyException(EasyException.DATABASE_EXCEPTION, result.Error);
return AddClientAppSettingResponse.Map(entity);
}
As you can see my handler has two dependencies ICurrentUserService , IRepositoryAccessor
My problem is IRepositoryAccessor when I run the test the repository object is null .
Here is my repository interface and imp ;
public interface IRepositoryAccessor
{
IRepository<TEntity> GetRepository<TEntity>(
string shard = "public",
DatabaseType type = DatabaseType.Raven,
Type inheritedRepository = null,
bool manualDisposing = false,
bool reThrowException=false) where TEntity : BaseEntity;
void CloseSession();
}
The imp :
public sealed class RepositoryAccessor : IRepositoryAccessor, IDisposable
{
private static readonly Dictionary<Type, object> FlyweightSqlGenerator = new();
private readonly List<IDisposable> _sessions = new();
private readonly ITracer _tracer;
private readonly IConfiguration _configuration;
public RepositoryAccessor(IConfiguration configuration, ITracer tracer = null)
{
_configuration = configuration;
_tracer = tracer;
}
public void CloseSession()
{
for (int i = 0; i < _sessions.Count; i++)
{
_sessions[i].Dispose();
}
_sessions.Clear();
}
public void Dispose() => CloseSession();
public IRepository<TEntity> GetRepository<TEntity>(
string shard = "public",
DatabaseType type = DatabaseType.Raven,
Type inheritedRepository = null,
bool manualDisposing = false,
bool reThrowException = false) where TEntity : BaseEntity
{
if (type == DatabaseType.Raven)
{
return GetRavenRepository<TEntity>(inheritedRepository, shard, manualDisposing, reThrowException);
}
else if (type == DatabaseType.Redis)
{
return new RedisRepository<TEntity>();
}
return GetSQLRepository<TEntity>(inheritedRepository, manualDisposing, reThrowException);
}
}
And here is my test :
[Fact]
public async void Test1()
{
//Arange
var mediator = new Mock<IMediator>();
var userservice = new Mock<ICurrentUserService>();
var repo = new Mock<IRepositoryAccessor>();
AddClientAppSettingCommand command = new AddClientAppSettingCommand(new domain.Entities.ClientAppSettings());
AddClientAppSettingCommandHandler handler = new AddClientAppSettingCommandHandler(userservice.Object,repo.Object);
//Act
var x = await handler.Handle(command, new System.Threading.CancellationToken());
}
And when I run the test with debug mode my repository is null :
I should define IAccessor and IRepository as a mock and setting up the Irepository for IAccessor as you can see :
var repoacc = new Mock<IRepositoryAccessor>();
var repo = new Mock<domain.Interfaces.IRepository<ClientAppSettings>>();
repoacc.Setup(i => i.GetRepository<ClientAppSettings>(It.IsAny<string>(), DatabaseType.Raven, null, false, true)).Returns(repo.Object);

XUnit mocked db connection dapper error, 'Object is not set to an instance of an object' when executing sql statement

I am trying to unit test my service layer as advised by #NKosi Here. I am able to do the integration test successfully by implementing the actual factory implementation without mocking anything but can't do the unit test (by mocking IDbConnection and my SQL connection factory class) as Dapper query executing fails with the error 'Object not set to an instance of an object'.
My IDbConnection factory and its implementation is as follow
public interface IDbConnectionFactory
{
IDbConnection CreateConnection();
}
public class ConnectionSetings
{
public string Name { get; set; }
}
public class SqlConnectionFactory : IDbConnectionFactory
{
private readonly ConnectionSetings connectionSettings;
public SqlConnectionFactory(ConnectionSetings connectionSettings)
{
this.connectionSettings = connectionSettings;
}
public IDbConnection CreateConnection()
{
return new SqlConnection(connectionSettings.Name);
}
}
And the XUnit test is as follow
[Fact]
public void Get_RestaurantById_ReturnsRestaurant()
{
//Arrange
var connection = new Mock<IDbConnection>();
var dbConnectionFactory = new Mock<IDbConnectionFactory>();
dbConnectionFactory.Setup(x => x.CreateConnection()).Returns(connection.Object);
//Act
var result = new SqlRestaurantDataCL(dbConnectionFactory.Object).Get(1);
//Assert
result.Name.Equals("Test Name 1");
//Assert.Equal("Test Name 1", result.Name);
}
And the Service Layer is as follow
public class SqlRestaurantDataCL : IRestaurantDataCL
{
private readonly IDbConnectionFactory factory;
public SqlRestaurantDataCL(IDbConnectionFactory factory)
{
this.factory = factory;
}
public Restaurant Get(int id)
{
using (var connection = factory.CreateConnection())
{
var selectSql = #"SELECT * From Restaurants Where Id = #Id";
var restaurant = connection.QuerySingleOrDefault<Restaurant>(selectSql, new
{
id
});
return restaurant;
}
}
}
Following is the error screenshot
Following is the answer to my question if anyone is in similar situation. Before following this solution, I would suggest to read #NKosi comments above and consult #Mikhail's solution Here.
ServiceStack.OrmLite.Sqlite package added to use in memory appraoch
internal class InMemoryDatabase
{
private readonly OrmLiteConnectionFactory dbFactory = new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider);
public IDbConnection OpenConnection() => this.dbFactory.OpenDbConnection();
public void Insert<T>(IEnumerable<T> items)
{
using (var db = this.OpenConnection())
{
db.CreateTableIfNotExists<T>();
foreach (var item in items)
{
db.Insert(item);
}
}
}
}
Data Access layer is as follow
public IEnumerable<Restaurant> GetAll()
{
using (var connection = factory.CreateConnection())
{
//return connection.Query<Restaurant>("Select * From [dbo].[Restaurants] Order By Name");
return connection.Query<Restaurant>("Select * From Restaurant Order By Name");
}
}
Unit test is as follow
[Fact]
public void Get_RestaurantById_ReturnsRestaurant()
{
//Arrange
var restaurants = new List<Restaurant>
{
new Restaurant { Id = 1, Name = "Test Name 1", Cuisine = CuisineType.None},
new Restaurant { Id = 2, Name = "Test Name 2", Cuisine = CuisineType.French},
new Restaurant { Id = 3, Name = "Test Name 3", Cuisine = CuisineType.German},
new Restaurant { Id = 4, Name = "Test Name 4", Cuisine = CuisineType.Italian},
new Restaurant { Id = 5, Name = "Test Name 5", Cuisine = CuisineType.None}
};
var db = new InMemoryDatabase();
db.Insert(restaurants);
var connection = new Mock<IDbConnection>();
var dbConnectionFactoryMock = new Mock<IDbConnectionFactory>();
dbConnectionFactoryMock.Setup(c => c.CreateConnection()).Returns(db.OpenConnection());
//Act
var result = new SqlRestaurantDataCL(dbConnectionFactoryMock.Object).GetAll();
//Assert
result.Should().BeEquivalentTo(restaurants);
}

ASP.NET Core unit test authorization

I try to create unit testing my authorization logic, but have problem for testing
await this.HttpContext.Authentication.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme)));
I have error
No authentication handler is configured to handle the scheme: Cookies
Because he need CookieAuthenticationOptions
But how configuration for unit test I don't know
private static Mock<SignInManager<User>> GetSignInManagerMock(Mock<UserManager<User>> userManagerMock)
{
var context = new Mock<HttpContext>();
var contextAccessor = new Mock<IHttpContextAccessor>();
contextAccessor.Setup(x => x.HttpContext).Returns(context.Object);
return new Mock<SignInManager<User>>(userManagerMock.Object,
contextAccessor.Object,
new Mock<IUserClaimsPrincipalFactory<User>>().Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<ILogger<SignInManager<User>>>().Object);
}
private static Mock<UserManager<User>> GetUserManagerMock()
{
return new Mock<UserManager<User>>(new Mock<IUserStore<User>>().Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<IPasswordHasher<User>>().Object,
new IUserValidator<User>[0],
new IPasswordValidator<User>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<IServiceProvider>().Object,
new Mock<ILogger<UserManager<User>>>().Object);
}
[Fact]
public async void Login_Corect_input_login_password_should_return_ok()
{
var stamp = Guid.NewGuid().ToString();
var user = new User
{
UserName = _fakeUserModel.UserName,
Email = _fakeUserModel.Email,
FirtName = _fakeUserModel.FirstName,
LastName = _fakeUserModel.LastName,
UserPicture = _fakeUserModel.UserPicture,
ConcurrencyStamp = stamp
};
var userManagerMock = GetUserManagerMock();
userManagerMock.Setup(s => s.FindByNameAsync(FakeData.UserName)).ReturnsAsync(user);
userManagerMock.Setup(s => s.GetRolesAsync(user)).ReturnsAsync(FakeData.Roles);
var signInManagerMock = GetSignInManagerMock(userManagerMock);
signInManagerMock.Setup(
s =>
s.PasswordSignInAsync(_fakeCorrectloginModel.UserName, _fakeCorrectloginModel.Password, false,
false))
.ReturnsAsync(Microsoft.AspNetCore.Identity.SignInResult.Success);
var controller = ControllerFactory.CreateFakeController<UserController>(false, userManagerMock.Object,
signInManagerMock.Object);
var response = await controller.Login(_fakeCorrectloginModel);
var result = Assert.IsType<JsonResult>(response);
var getModel = Assert.IsType<UserViewModel>(result.Value);
Assert.Equal(_fakeUserModel, getModel);
}
public static class ControllerFactory
{
public static T CreateFakeController<T>(bool isLoggedIn, params object[] arg) where T : Controller
{
var fakePrincipal = GetPrincipalMock(isLoggedIn).Object;
var fakeActionContext = new ActionContext
{
HttpContext = new DefaultHttpContext
{
User = fakePrincipal
},
ActionDescriptor = new ControllerActionDescriptor(),
RouteData = new RouteData()
};
var controller = (T)Activator.CreateInstance(typeof(T), arg);
controller.ControllerContext = new ControllerContext(fakeActionContext);
return controller;
}
public static Mock<ClaimsPrincipal> GetPrincipalMock(bool isLoggedIn)
{
var principalMock = new Mock<ClaimsPrincipal>();
principalMock.Setup(sg => sg.Identity).Returns(GetIdentityMock(isLoggedIn).Object);
principalMock.Setup(s => s.IsInRole(It.IsAny<string>())).Returns(false);
principalMock.Setup(s => s.Claims).Returns(new List<Claim>
{
GetClaim(HelpClaimTypes.Language, "ua")
});
return principalMock;
}
public static Mock<ClaimsIdentity> GetIdentityMock(bool isLoggedIn)
{
var identityMock = new Mock<ClaimsIdentity>();
identityMock.Setup(sg => sg.AuthenticationType).Returns(isLoggedIn ? FakeData.AuthenticationType : null);
identityMock.Setup(sg => sg.IsAuthenticated).Returns(isLoggedIn);
identityMock.Setup(sg => sg.Name).Returns(isLoggedIn ? FakeData.UserName : null);
return identityMock;
}
public static ClaimsIdentity GetClaimsIdentity(params Claim[] claims)
{
var identityMock = new ClaimsIdentity(claims);
return identityMock;
}
public static Claim GetClaim(string type, string value)
{
return new Claim(type, value);
}
}

Unit testing generic htmlHelper methods with nunit

I'm new to nUnit and I've been tasked with creating unit tests for some htmlhelper extension methods.
How should I go about creating a unit test for the following method?
public static MvcHtmlString EnumDropDownListForOrderBy<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TEnum>> expression, bool orderById, string firstElement = null, object htmlAttributes = null)
{
ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items = values.Select(value => new SelectListItem()
{
Text = value.GetAttributeFrom<DescriptionAttribute>(value.ToString()).Description,
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
});
IEnumerable<SelectListItem> itemsFiltered = items.Where(e => !string.IsNullOrEmpty(e.Text)).AsEnumerable();
itemsFiltered = itemsFiltered.OrderBy(e => (orderById ? e.Text : e.Value));
return htmlHelper.DropDownListFor(
expression,
itemsFiltered,
firstElement,
htmlAttributes
);
}
Any help would be appreciated
Below is how you write a Unit Test for this. Note that since you have not specified that you use a Mock object framework I'm going to the poor man technique, which is the hand written stubs and mocks. There is also another helper method if you are using Moq.
It is important to note that, in order to simplify the code execution I have made couple of changes to your extension method, so the test would not fail unexpectedly. Checking for any unexpected behaver is a good defensive programming practice anyway.
Back to the tests.
SUT (System Under Test)
This is how the SUT (System Under Test) looks like and supporting types looks like. (Please feel free to modify to your need accordingly)
public static class MyHtmlHelper
{
public static MvcHtmlString EnumDropDownListForOrderBy<TModel, TEnum>
(this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TEnum>> expression,
bool orderById, string firstElement = null, object htmlAttributes = null,
Func<ModelMetadata> fromLambFunc = null)
{
ModelMetadata metadata =
ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
Type enumType = GetNonNullableModelType(metadata);
IEnumerable<TEnum> values = Enum.GetValues(enumType).Cast<TEnum>();
IEnumerable<SelectListItem> items =
values.Select(value => new SelectListItem()
{
Text = GetText(value),
Value = value.ToString(),
Selected = value.Equals(metadata.Model)
});
IEnumerable<SelectListItem> itemsFiltered =
items.Where(e => !string.IsNullOrEmpty(e.Text)).AsEnumerable();
itemsFiltered = itemsFiltered.OrderBy(e => (orderById ? e.Text : e.Value));
return htmlHelper.DropDownListFor
(expression, itemsFiltered, firstElement, htmlAttributes);
}
private static Type GetNonNullableModelType(ModelMetadata metadata) {
return typeof (SomeEnum);
}
private static string GetText<TEnum>(TEnum value) {
return value.GetAttributeFrom<DescriptionAttribute>(value.ToString()) != null
? value.GetAttributeFrom<DescriptionAttribute>(value.ToString()).Description
: string.Empty;
}
}
public static class ExtensionMethodsAttr
{
public static T GetAttributeFrom<T>(this object instance, string propertyName)
where T : Attribute
{
var attrType = typeof(T);
var property = instance.GetType().GetProperty(propertyName);
return property != null ?
(T)property.GetCustomAttributes(attrType, false).First() : default(T) ;
}
}
public enum SomeEnum { A,}
Unit Tests
[TestFixture]
public class HtmlHelperTests
{
[Test]
public void EnumDropDownListForOrderBy_InvokeDropDownListFor_ReturnsExpectedSelectItemResult()
{
//Arrange
var expected = "<select id=\"Foo\" name=\"Foo\"></select>";
var fakeHtmlHelper = CreateHtmlHelperStaticStubs
(new ViewDataDictionary(new FakeViewModel() {Foo = SomeEnum.A}));
//var fakeHtmlHelper = CreateHtmlHelperUsingMoq
(new ViewDataDictionary(new FakeViewModel(){Foo = SomeEnum.A}));
//Act
var result = fakeHtmlHelper.EnumDropDownListForOrderBy
(model => model.Foo, It.IsAny<bool>(), null, null, null);
//Assert
Assert.AreEqual(expected, result.ToString());
}
private static HtmlHelper<FakeViewModel>
CreateHtmlHelperStaticStubs(ViewDataDictionary viewData)
{
var stubControllerContext = new ControllerContext(new FakeHttpContext(), new RouteData(), new FakeController());
var stubViewContext = new ViewContext(stubControllerContext, new FakeView(),
new ViewDataDictionary(new FakeViewModel() { Foo = SomeEnum.A }),
new TempDataDictionary(), new TextMessageWriter());
var fakeViewDataContainer = new FakeViewDataContainer();
fakeViewDataContainer.ViewData = viewData;
return new HtmlHelper<FakeViewModel>(stubViewContext, fakeViewDataContainer);
}
//Moq version
private static HtmlHelper<FakeViewModel>
CreateHtmlHelperUsingMoq(ViewDataDictionary viewData)
{
var stubControllerContext = new Mock<ControllerContext>();
stubControllerContext.Setup(x => x.HttpContext).Returns(new Mock<HttpContextBase>().Object);
stubControllerContext.Setup(x => x.RouteData).Returns(new RouteData());
stubControllerContext.Setup(x => x.Controller).Returns(new Mock<ControllerBase>().Object); ;
var stubViewContext = new Mock<ViewContext>();
stubViewContext.Setup(x => x.View).Returns(new Mock<IView>().Object);
stubViewContext.Setup(x => x.ViewData).Returns(viewData);
stubViewContext.Setup(x => x.TempData).Returns(new TempDataDictionary());
var mockViewDataContainer = new Mock<IViewDataContainer>();
mockViewDataContainer.Setup(v => v.ViewData).Returns(viewData);
return new HtmlHelper<FakeViewModel>(stubViewContext.Object, mockViewDataContainer.Object);
}
}
class FakeHttpContext : HttpContextBase
{
private Dictionary<object, object> _items = new Dictionary<object, object>();
public override IDictionary Items { get { return _items; } }
}
class FakeViewDataContainer : IViewDataContainer
{
private ViewDataDictionary _viewData = new ViewDataDictionary();
public ViewDataDictionary ViewData { get { return _viewData; } set { _viewData = value; } }
}
class FakeController : Controller { }
class FakeView : IView
{
public void Render(ViewContext viewContext, System.IO.TextWriter writer)
{
throw new NotImplementedException();
}
}
public class FakeViewModel {
public SomeEnum Foo { get; set; }
}

How can I mock ServiceStack IHttpRequest

I'm trying to get a unit test working for a service that is injecting items into the IHttpRequest.Items, using a request filter:
this.RequestFilters.Add((req, res, dto) =>
{
// simplified for readability...
var repo = container.Resolve<IClientRepository>();
var apiKey = req.Headers["ApiKey"];
// lookup account code from api key
var accountcode = repo.GetByApiKey(apiKey);
req.Items.Add("AccountCode", accountCode);
});
My service uses that dictionary item:
public class UserService : AppServiceBase
{
public IUserServiceGateway UserServiceGateway { get; set; }
public object Any(UserRequest request)
{
var accountCode = base.Request.Items["AccountCode"].ToString();
var user = UserServiceGateway.GetUserByUsername(request.Name);
return new UserResponse { User = user };
}
}
My test needs be somehow to mock the request, and insert that account code item:
[Test]
public void ValidUsernameReturnUser()
{
// arrange
var gateway = new Mock<IUserServiceGateway>();
gateway.Setup(s => s.GetUserByUsername(It.IsAny<string>()))
.Returns(new UserAccountDTO { Forename = "John", Surname = "Doe" });
var service = new UserService {
UserServiceGateway = gateway.Object,
RequestContext = new MockRequestContext(),
//Request = has no setter
};
// request is this case is null
base.Request.Items.Add("AccountCode", "DEF456");
// act
var response = (UserResponse)service.Any(new UserRequest { Name = "test" });
// assert
Assert.That(response.Result, Is.Not.Null);
}
The service itself accepts a mocked RequestContext, but not a Request. The test therefore fails. Is there a better way to do this?
I think this should do it.
[Test]
public void ValidUsernameReturnUser()
{
// arrange
var mockRequestContext = new MockRequestContext();
//add items to Request
mockRequestContext.Get<IHttpRequest>().Items.Add("AccountCode", "DEF456");
var gateway = new Mock<IUserServiceGateway>();
gateway.Setup(s => s.GetUserByUsername(It.IsAny<string>()))
.Returns(new UserAccountDTO { Forename = "John", Surname = "Doe" });
var service = new UserService {
UserServiceGateway = gateway.Object,
RequestContext = new MockRequestContext(),
};
// act
var response = (UserResponse)service.Any(new UserRequest { Name = "test" });
// assert
Assert.That(response.Result, Is.Not.Null);
}