Mock is not returning setup value - asp.net-core

I've below method which I'm unit testing using Xunit and Moq.
public class PersonService : IPersonService
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
public PersonService(IUnitOfWork unitOfWork, IMapper mapper)
{
_unitOfWork = unitOfWork ?? throw new ArgumentNullException(nameof(unitOfWork));
_mapper = mapper;
}
public async Task<int> PostPersonAsync(PersonModel person)
{
int result = 0;
using (_unitOfWork.Connection)
{
try
{
_unitOfWork.OpenConnection();
_unitOfWork.Begin();
var PersonDto = _mapper.Map<PersonDto>(person);
result = await _unitOfWork.PersonRepository.PostPersonAsync(PersonDto, _unitOfWork.Transaction);
_unitOfWork.Commit();
_unitOfWork.CloseConnection();
}
catch (Exception ex)
{
_unitOfWork.Rollback();
throw;
}
}
return result;
}
}
Below is my Xunit method:
[Fact]
public void PostPersonAsync_Should_SavePerson()
{
//Arrange
var _IDbTransaction = new Mock<IDbTransaction>();
var _unitOfWorkMock1 = new Mock<IUnitOfWork>();
var PersonDto = _mapper.Map<PersonDto>(PersonServiceData.PersonModel);
int numberofAffectedRows = 5;
_unitOfWorkMock1.Setup(s => s.OpenConnection());
_unitOfWorkMock1.Setup(s => s.PersonRepository.PostPersonAsync(PersonDto, _IDbTransaction.Object)).ReturnsAsync(()=>numberofAffectedRows);
_unitOfWorkMock1.Setup(s => s.CloseConnection());
_target = new PersonService(_unitOfWorkMock1.Object, _mapper);
//Act
var result = _target.PostPersonAsync(PersonServiceData.PersonModel).Result;
//Assert
Assert.Equal(5, result);
}
I'm not sure why it still returns zero, and my test case fails.
I've also tried with the below, but still, my test case fails.
_unitOfWorkMock1.Setup(s => s.PersonRepository.PostPersonAsync(PersonDto, _IDbTransaction.Object)).ReturnsAsync(()=>numberofAffectedRows);
Even after setting up the return value for the repository method call, it is returning zero.

Try this:
_unitOfWorkMock1
.Setup(s => s.PersonRepository.PostPersonAsync(It.IsAny<PersonDto>(), It.IsAny<IDbTransaction>()))
.ReturnsAsync(numberofAffectedRows);

Related

Shopifysharp AuthorizationService.IsAuthenticRequest Returns false

Please see the following code snippet:
This is my controller:
[Produces("application/json")]
[Route("api/Shopify")]
[AllowAnonymous]
[ServiceFilter(typeof(ShopifyVerificationFilter))]
//[ApiExplorerSettings(IgnoreApi = true)]
public class ShopifyController : Controller
{
private readonly ILogger logger;
public ShopifyController(ILoggerFactory loggerFactory)
{
logger = loggerFactory.CreateLogger<StoreLocatorController>();
}
[HttpGet("fetch_stock.json")]
public async Task<IActionResult> GetInventoryLevels(ShopifyFetchStock shopifyFetchStock, [FromServices] IShopifyFulfillmentServices shopifyFulfillmentServices)
{
try
{
var inventoryData = await shopifyFulfillmentServices.GetInventoryLevels(shopifyFetchStock);
return Ok(inventoryData);
}
catch (Exception ex)
{
return Ok();
}
}
}
This is my ShopifyVerificationFilter:
public class ShopifyVerificationFilter : Attribute, IAuthorizationFilter
{
private readonly IOptions<ShopifySettings> _shopifySettings;
private readonly IShopifyVerify _shopifyVerify;
public ShopifyVerificationFilter(IOptions<ShopifySettings> shopifySettings, IShopifyVerify shopifyVerify)
{
_shopifySettings = shopifySettings;
_shopifyVerify = shopifyVerify;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
var isVerified = _shopifyVerify.IsAuthenticShopifyRequest(context.HttpContext.Request.QueryString.Value, _shopifySettings.Value.APISecretKey);
if (!isVerified)
{
context.HttpContext.Request.EnableRewind();
isVerified = _shopifyVerify.IsAuthenticShopifyWebhook(context.HttpContext.Request.Headers, context.HttpContext.Request.Body, _shopifySettings.Value.APISecretKey, context.HttpContext.Request.QueryString.Value);
if (!isVerified)
{
context.Result = new UnauthorizedResult();
}
else
{
context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
}
}
}
}
This is the implementation for the IsAuthenticShopifyRequest method:
public class ShopifyVerify : IShopifyVerify
{
public bool IsAuthenticShopifyRequest(string queryString, string APIKey)
{
var result = AuthorizationService.IsAuthenticRequest(queryString, APIKey);
return result;
}
}
When a call is made to AuthorizationService.IsAuthenticShopifyRequest(string queryString, string APIKey), it always returns false and thus not able to authenticate the shop. This piece of code was running without error before now. This issue started some couple of weeks back.
Did anything change in shopifysharp? If not please what do I need to do to get this work and if shopifysharp changed the implementation of AuthorizationService.IsAuthenticRequest(queryString, APIKey); please I need help in resolving this.
Thanks.

xUnit, Moq with UnitOfWork and general repository

I tried a lot of examples but I do not get the good response.
The ReportUpload method creates some Report entity based on the list from ExcelManager list
and adds them to the Reports DbSet.
My goal would be to read out the added entities from the mocked DbSet and assert them.
How can I pass the mocked DbContext and Dbset into UnitOfWork, please?
GeneralRepository.cs
public class GeneralRepository<TContext, TEntity> : IGeneralRepository<TEntity>
where TEntity : class
where TContext : DbContext
{
protected readonly TContext _context;
protected readonly DbSet<TEntity> dbSet;
public GeneralRepository(TContext context)
{
_context = context;
dbSet = _context.Set<TEntity>();
}
public async Task AddAsync(TEntity entity)
{
await _context.Set<TEntity>().AddAsync(entity);
}
...
}
IUnitOfWork.cs
public interface IUnitOfWork : IDisposable
{
IGeneralRepository<Report> Reports{ get; }
...
}
UnitOfWork.cs
public sealed class UnitOfWork : IUnitOfWork
{
private readonly MyDbContext _context;
public UnitOfWork(MyDbContext context)
{
_context = context;
}
private IGeneralRepository<Report>_report;
public IGeneralRepository<Report> Reports => _report ??= new GeneralRepository<MyDbContext, Report>(_context);
...
}
ReportService.cs
public class ReportService : GeneralService, IReportService
{
private readonly IExcelManager _excelManager;
public ReportService(IUnitOfWork unitOfWork, IExcelManager excelManager)
{
UnitOfWork = unitOfWork;
_excelManager = excelManager;
}
public async Task<string> ReportUpload(MemoryStream ms)
{
var workingList = _excelManager.ReadExcel(ms);
var i = 0;
while (i < workingList.Count)
{
var report = new Report { ... }
await UnitOfWork.Reports.AddAsync(report);
}
....
}
ReportServiceTest.cs
public class ReportServiceTests
{
[Fact()]
public async Task ReportUploadTest()
{
//Arrange
....
var mockSet = new Mock<DbSet<Report>>();
var mockContext = new Mock<MyDbContext>();
mockContext.Setup(x => x.Reports).Returns(mockSet.Object);
var reportRepositoryMock = new Mock<IGeneralRepository<Report>>();
reportRepositoryMock.Setup(m => m.AddAsync(It.IsAny<Report>()));
var unitOfWorkMock = new Mock<IUnitOfWork>();
unitOfWorkMock.Setup(p => p.Reports)
.Returns(reportRepositoryMock.Object);
...
//Act
var reportService = new ReportService(unitOfWorkMock.Object,exelManagerMock.Object);
await reportService.ReportUpload(new MemoryStream());
//Assert
???
}
DbContext cannot be passed to the UnitOfWork object because its context field is private.
I had to use SQLite in memory to test the GeneralRepository method.
var exelManagerMock = new Mock<IExcelManager>();
exelManagerMock.Setup(p => p.ReadExcel(It.IsAny<MemoryStream>()))
.Returns(listOfExcelReadResult);
var dbFixture = new DatabaseFixture();
var context = dbFixture.CreateContext();
var unitOfWork = new UnitOfWork(context);
//I need some plus data
await unitOfWork.Providers.AddRangeAsync(providers);
await context.SaveChangesAsync();
var reportService = new ReportService(unitOfWork, exelManagerMock.Object);
await reportService.ReportUpload(new MemoryStream(), 2021);
var allReports = await reportService.UnitOfWork.Reports.GetAsync();
Assert.Equal(3, allReports.Count);

Unit test exception when calling API service using IHttpContextAccessor [duplicate]

I have a method to get header value using IHttpContextAccessor
public class HeaderConfiguration : IHeaderConfiguration
{
public HeaderConfiguration()
{
}
public string GetTenantId(IHttpContextAccessor httpContextAccessor)
{
return httpContextAccessor.HttpContext.Request.Headers["Tenant-ID"].ToString();
}
}
I am testing GetBookByBookId method
Let's say the method looks like this:
public class Book
{
private readonly IHttpContextAccessor _httpContextAccessor;
private IHeaderConfiguration _headerConfiguration;
private string _tenantID;
public Book(IHeaderConfiguration headerConfiguration, IHttpContextAccessor httpContextAccessor){
var headerConfig = new HeaderConfiguration();
_httpContextAccessor = httpContextAccessor;
_tenantID = headerConfig.GetTenantId(_httpContextAccessor);
}
public Task<List<BookModel>> GetBookByBookId(string id){
//do something with the _tenantId
//...
}
}
Here's my unit test for GetBookByBookId method
[Fact]
public void test_GetBookByBookId()
{
//Arrange
//Mock IHttpContextAccessor
var mockHttpContextAccessor = new Mock<IHttpContextAccessor>();
mockHttpContextAccessor.Setup(req => req.HttpContext.Request.Headers["Tenant-ID"].ToString()).Returns(It.IsAny<string>());
//Mock HeaderConfiguration
var mockHeaderConfiguration = new Mock<IHeaderConfiguration>();
mockHeaderConfiguration.Setup(x => x.GetTenantId(mockHttpContextAccessor.Object)).Returns(It.IsAny<string>());
var book = new Book( mockHttpContextAccessor.Object, mockHeaderConfiguration.Object);
var bookId = "100";
//Act
var result = book.GetBookByBookId(bookId);
//Assert
result.Result.Should().NotBeNull().And.
BeOfType<List<BookModel>>();
}
But for this line:
mockHttpContextAccessor.Setup(req => req.HttpContext.Request.Headers["Tenant-ID"].ToString()).Returns(It.IsAny<string>());
It says
System.NotSupportedException: 'Type to mock must be an interface or an abstract or non-sealed class. '
I was wondering what's the proper way to mock IHttpContextAccessor with header value?
You can use the DefaultHttpContext as a backing for the IHttpContextAccessor.HttpContext. Saves you having to set-up too many things
Next you cannot use It.IsAny<string>() as a Returns result. They were meant to be used in the set up expressions alone.
Check the refactor
[Fact]
public async Task test_GetBookByBookId() {
//Arrange
//Mock IHttpContextAccessor
var mockHttpContextAccessor = new Mock<IHttpContextAccessor>();
var context = new DefaultHttpContext();
var fakeTenantId = "abcd";
context.Request.Headers["Tenant-ID"] = fakeTenantId;
mockHttpContextAccessor.Setup(_ => _.HttpContext).Returns(context);
//Mock HeaderConfiguration
var mockHeaderConfiguration = new Mock<IHeaderConfiguration>();
mockHeaderConfiguration
.Setup(_ => _.GetTenantId(It.IsAny<IHttpContextAccessor>()))
.Returns(fakeTenantId);
var book = new Book(mockHttpContextAccessor.Object, mockHeaderConfiguration.Object);
var bookId = "100";
//Act
var result = await book.GetBookByBookId(bookId);
//Assert
result.Should().NotBeNull().And.
BeOfType<List<BookModel>>();
}
There may also be an issue with the Class Under Test as it is manually initializing the HeaderConfiguration when it should actually be explicitly injected.
public Book(IHeaderConfiguration headerConfiguration, IHttpContextAccessor httpContextAccessor) {
_httpContextAccessor = httpContextAccessor;
_tenantID = headerConfiguration.GetTenantId(_httpContextAccessor);
}
In my scenario I had to mock IHttpContextAccessor and access the inner request url bits.
I'm sharing it here because I spent a decent amount of time figuring this out and hopefully it'll help someone.
readonly Mock<IHttpContextAccessor> _HttpContextAccessor =
new Mock<IHttpContextAccessor>(MockBehavior.Strict);
void SetupHttpContextAccessorWithUrl(string currentUrl)
{
var httpContext = new DefaultHttpContext();
setRequestUrl(httpContext.Request, currentUrl);
_HttpContextAccessor
.SetupGet(accessor => accessor.HttpContext)
.Returns(httpContext);
static void setRequestUrl(HttpRequest httpRequest, string url)
{
UriHelper
.FromAbsolute(url, out var scheme, out var host, out var path, out var query,
fragment: out var _);
httpRequest.Scheme = scheme;
httpRequest.Host = host;
httpRequest.Path = path;
httpRequest.QueryString = query;
}
}
If you are making use of the wonderful NSubstitute package for NUnit, you can do this...
var mockHttpAccessor = Substitute.For<IHttpContextAccessor>();
var context = new DefaultHttpContext
{
Connection =
{
Id = Guid.NewGuid().ToString()
}
};
mockHttpAccessor.HttpContext.Returns(context);
// usage...

A second operation started on this context before a previous operation completed

I have a project with asp.net core and entity framework core, for performance reasons I use MemoryCache. ForumQueryManager class is for querying forum data. This class for data uses the CacheManager Get method and passes cache key and timeout cache time and a method for when the cache is empty for retrieving data from the database. this code work almost always. but sometimes throw an exception
Exception:
An unhandled exception occurred while processing the request.
InvalidOperationException: A second operation started on this context
before a previous operation completed. Any instance members are not
guaranteed to be thread safe.
Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()
ForumQueryManager:
public class ForumQueryManager : IForumQueryManager
{
private readonly ApplicationDbContext _dbContext;
private readonly ICalender _calender;
private readonly ICacheManager _cacheManager;
public ForumQueryManager(ApplicationDbContext dbContext, ICacheManager cacheManager)
{
_dbContext = dbContext;
_cacheManager = cacheManager;
}
public async Task<List<ForumCategoryDto>> GetAll()
{
var items = await _cacheManager.Get(CacheConstants.ForumCategories, 20, GetForumCategories);
return items;
}
private async Task<List<ForumCategoryDto>> GetForumCategories()
{
var categories = await _dbContext.ForumCategories
.Select(e => new ForumCategoryDto
{
Name = e.Name,
ForumCategoryId = e.ForumCategoryId
}).ToListAsync();
return categories;
}
}
CacheManager:
public class CacheManager: ICacheManager
{
private readonly IMemoryCache _cache;
private readonly CacheSetting _cacheSetting;
public CacheManager(IMemoryCache cache, IOptions<CacheSetting> cacheOption)
{
_cache = cache;
_cacheSetting = cacheOption.Value;
}
public async Task<List<T>> Get<T>(string cacheKey, int expirationMinutes, Func<Task<List<T>>> function)
{
List<T> items;
if (_cacheSetting.MemeoryEnabled)
{
var value = _cache.Get<string>(cacheKey);
if (value == null)
{
items = await function();
value = JsonConvert.SerializeObject(items, Formatting.Indented,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
_cache.Set(cacheKey, value,
new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromMinutes(expirationMinutes)));
}
else
{
items = JsonConvert.DeserializeObject<List<T>>(value);
}
}
else
{
items = await function();
}
return items;
}
}
ForumQueryManager must be transient, otherwise the _dbContext variable will be reused.

SignalR OnDisconnected event not persisting data to DB

I have a SignalR hub in which I'm injecting service classes which persist data to a local SQL Server instance via Castle Windsor.
The hub looks like:
[Authorize]
public class MyHub : Hub
{
private readonly IHubService _hubService;
private readonly IHubUserService _hubUserService;
private readonly IUserService _userService;
public MyHub(IHubService hubService, IHubUserService hubUserService, IUserService userService)
{
_hubService = hubService;
_hubUserService = hubUserService;
_userService = userService;
}
public async Task JoinHub(Guid hubId)
{
var hub = _hubService.GetHubById(hubId);
if (hub == null)
throw new NotFoundException(String.Format("Hub ({0}) was not found.", hubId.ToString()));
var userName = Context.User.Identity.Name;
var user = _userService.GetUserByUserName(userName);
if (user == null)
throw new NotFoundException(String.Format("User ({0}) was not found.", userName));
var hubUser = new HubUser
{
User = user,
Hub = hub,
ConnectionId = Context.ConnectionId
};
// Persist a new HubUser to the DB
hubUser = _hubUserService.InsertHubUser(hubUser);
await Groups.Add(Context.ConnectionId, hub.Id.ToString());
Clients.Group(hub.Id.ToString()).addChatMessage(userName + " has joined.");
}
public async Task LeaveHub()
{
var userName = Context.User.Identity.Name;
var hubUser = _hubUserService.GetHubUserByUserName(userName);
// Removes HubUser from the DB
_hubUserService.RemoveHubUser(hubUser);
await Groups.Remove(Context.ConnectionId, hubUser.Hub.Id.ToString());
Clients.Group(hubUser.Hub.Id.ToString()).addChatMessage(userName + " has left.");
}
public override Task OnDisconnected(bool stopCalled)
{
var userName = Context.User.Identity.Name;
var hubUser = _hubUserService.GetHubUserByUserName(userName);
// Removes HubUser from the DB
_hubUserService.RemoveHubUser(hubUser); // This line executes but does not persist anything to DB
Groups.Remove(Context.ConnectionId, hubUser.Hub.Id.ToString());
Clients.Group(hubUser.Hub.Id.ToString()).addChatMessage(userName + " has left.");
return base.OnDisconnected(stopCalled);
}
}
When calling JoinHub and LeaveHub methods from the client, everything works fine. However, when the OnDisconnected method fires, nothing is deleted from the database. I can see that the code does indeed execute, but the record remains in the DB and does not get deleted.
I'm wondering if perhaps my nhibernate session is not committing the transaction to the database due to castle windsor's dependency lifetimes or something, however, it's odd that LeaveHub executes as expected but the same code does not in the OnDisconnected method.
My dependencies are registered with the following configuration as per this blog post.
Kernel.Register(
//Nhibernate session factory
Component.For<ISessionFactory>().UsingFactoryMethod(CreateNhSessionFactory).LifeStyle.Singleton,
//Nhibernate session
Component.For<ISession>().UsingFactoryMethod(kernel => kernel.Resolve<ISessionFactory>().OpenSession()).LifeStyle.HybridPerWebRequestTransient()
);
and I also register an interceptor to implement a unit of work pattern:
// Unitofwork interceptor
Component.For<NhUnitOfWorkInterceptor>().LifeStyle.HybridPerWebRequestTransient()
If anyone can give any input on why the method LeaveHub works correctly and why it fails to persist anything in the OnDisconnected method, that'd be greatly appreciated.
Just an FYI Nhibernate Sessions don't do so well using async as they are not threadsafe at all. Try running things synchronously and see what you get.
Is Nhibernate set to flush on transaction commit? I can't comment becasue I am a newbie but I ran into this issue some time ago. I am not using FluentNhibernate but I am sure there is a config option to set flush on transaction commit. This is assuming you are wrapping all open session calls in a transaction. I use something like this for sessions. Also go get Nhibernate Profiler it is a godsend.
public class SessionManager : ISessionManager
{
private readonly ISessionFactory _sessionFactory;
private ISession _currentSession;
private ITransaction _currentTransaction;
public SessionManager(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
}
public ISession OpenSession()
{
if (CurrentSessionContext.HasBind(_sessionFactory))
{
_currentSession = _sessionFactory.GetCurrentSession();
}
else
{
_currentSession = _sessionFactory.OpenSession();
CurrentSessionContext.Bind(_currentSession);
}
CurrentSessionContext.Bind(_currentSession);
_currentTransaction = _currentSession.BeginTransaction();
return _currentSession;
}
public void Dispose()
{
try
{
if (_currentTransaction != null && _currentTransaction.IsActive)
_currentTransaction.Commit();
}
catch (Exception)
{
if (_currentTransaction != null) _currentTransaction.Rollback();
throw;
}
finally
{
if (_currentSession != null)
{
if (_currentTransaction != null) _currentTransaction.Dispose();
_currentSession.Close();
}
}
}
}
Here is my configuration, I am using it on several apps. On a side not there is a reason I don't use FluentNhibernate, The mapping by code built in is awesome and flexible. Let me know I can send you some sample mappings.
public class SessionFactoryBuilder
{
public static ISessionFactory BuildSessionFactory(string connectionString)
{
var cfg = new Configuration();
cfg.DataBaseIntegration(db =>
{
db.Dialect<MsSql2012Dialect>();
db.Driver<Sql2008ClientDriver>();
db.ConnectionString = connectionString;
db.BatchSize = 1500;
db.LogSqlInConsole = false;
db.PrepareCommands = true;
db.ConnectionReleaseMode = ConnectionReleaseMode.AfterTransaction;
db.IsolationLevel = IsolationLevel.ReadCommitted;
})
.SetProperty(Environment.CurrentSessionContextClass, "web")
.SetProperty(Environment.UseSecondLevelCache, "true")
.SetProperty(Environment.ShowSql, "true")
.SetProperty(Environment.PrepareSql, "true")
.Cache(c =>
{
c.UseQueryCache = true;
c.Provider<RtMemoryCacheProvider>();
c.DefaultExpiration = 1440;
}).SessionFactory().GenerateStatistics();
HbmMapping mapping = GetMappings();
cfg.AddDeserializedMapping(mapping, "AppName");
SchemaMetadataUpdater.QuoteTableAndColumns(cfg);
return cfg.BuildSessionFactory();
}
private static HbmMapping GetMappings()
{
var mapper = new ModelMapper();
mapper.AddMappings(typeof (UserMap).Assembly.GetTypes());
HbmMapping mapping = mapper.CompileMappingForAllExplicitlyAddedEntities();
return mapping;
}
}
Here is a neat little bit for managing SignalR dependencies with Castle. You may want to give this a try just for giggles.
public class SignalRDependencyResolver : Microsoft.AspNet.SignalR.DefaultDependencyResolver
{
private readonly IWindsorContainer _container;
public SignalRDependencyResolver(IWindsorContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
}
public override object GetService(Type serviceType)
{
return TryGet(serviceType) ?? base.GetService(serviceType);
}
public override IEnumerable<object> GetServices(Type serviceType)
{
return TryGetAll(serviceType).Concat(base.GetServices(serviceType));
}
[DebuggerStepThrough]
private object TryGet(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (Exception)
{
return null;
}
}
private IEnumerable<object> TryGetAll(Type serviceType)
{
try
{
Array array = _container.ResolveAll(serviceType);
return array.Cast<object>().ToList();
}
catch (Exception)
{
return null;
}
}
}
Put this in global asax before you set your controller factory
// SignalR
_container.Register(Classes.FromThisAssembly().BasedOn(typeof(IHub)).LifestyleTransient());
SignalRDependencyResolver signalRDependencyResolver = new SignalRDependencyResolver(_container);
Microsoft.AspNet.SignalR.GlobalHost.DependencyResolver = signalRDependencyResolver;