Mocking and Unit Testing ASP.Net 1.0 Repository - c#

I am in need of some help Mocking and testing my class. I have tried various methods and feel this is the closest I have came. //1 and //2 are two separate attempts.
There is no error on method one but I do not know how to actually test anything with it using the Assert call.
Attempt 2 has the error message
Can not instantiate proxy of class: RentalsRated.Data.RentalsDBContext.
Test
[Fact]
public void RepoUA_GetAll()
{
var users = new List<UserAccount> {
new UserAccount { Id = "idstring1", Username = "username1"},
new UserAccount { Id = "idstring2", Username = "username2" },
new UserAccount { Id = "idstring3", Username = "username3" },
}.AsQueryable();
var mockContext = new Mock<RentalsDBContext>();
var mockSet = new Mock<DbSet<UserAccount>>();
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Provider).Returns(users.Provider);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.Expression).Returns(users.Expression);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.ElementType).Returns(users.ElementType);
mockSet.As<IQueryable<UserAccount>>().Setup(m => m.GetEnumerator()).Returns(users.GetEnumerator());
mockContext.Setup(m => m.Set<UserAccount>()).Returns(mockSet.Object).Verifiable();
//1
Mock<IRentalsRepository<UserAccount>> MockRepo = new Mock<IRentalsRepository<UserAccount>>();
MockRepo.Setup(m => m.GetAll()).Returns(users);
//2
var testClass = new RentalsRepository<UserAccount>(mockContext.Object);
var result = testClass.Get("idstring2");
Assert.Equal("idstring2", result.Id);
}
Repo
public class RentalsRepository<T> : IRentalsRepository<T> where T : BaseClass
{
private readonly RentalsDBContext _Context;
private DbSet<T> entities;
string errorMessage = string.Empty;
public RentalsRepository(RentalsDBContext _Context)
{
this._Context = _Context;
entities = _Context.Set<T>();
}
public IEnumerable<T> GetAll()
{
return entities.AsEnumerable();
}
}
Context
public class RentalsDBContext : DbContext
{
public RentalsDBContext(DbContextOptions<RentalsDBContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
public virtual DbSet<UserAccount> UserAccounts { get; set; }
public virtual DbSet<Rating> Ratings { get; set; }
public virtual DbSet<PropertyAddress> PropertyAddresses { get; set; }
public virtual DbSet<Town> Towns { get; set; }
public virtual DbSet<County> Countys { get; set; }
public virtual DbSet<RatingImage> RatingImages { get; set; }
}

You are going to be a default constructor for the RentalsDBContext as Moq is unable to instantiate the class with its current constructor.
public class RentalsDBContext : DbContext {
public RentalsDBContext() : base() { }
public RentalsDBContext(DbContextOptions<RentalsDBContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
//...other code removed for brevity
}

Related

Multiple in-memory databases with the same name

In relation of this answer, I'm trying to get multiple context to work by setting UseInMemoryDatabase to the same name. The test below fails, and the secondContext is empty.
What else do I need to do to share the same in memory database?
[Test]
public void MultipleContextTest()
{
var firstContext = new FirstContext(new DbContextOptionsBuilder<FirstContext>().UseInMemoryDatabase("DB").Options);
firstContext.Add(new Entity() {Name = "Test"});
firstContext.SaveChanges();
var secondContext = new SecondContext(new DbContextOptionsBuilder<SecondContext>().UseInMemoryDatabase("DB").Options);
Assert.AreEqual(1, secondContext.Entity.Count());
}
public class FirstContext : DbContext
{
public DbSet<Entity> Entity { get; set; }
public FirstContext(DbContextOptions options) : base(options)
{
}
}
public class SecondContext : DbContext
{
public DbSet<Entity> Entity { get; set; }
public SecondContext(DbContextOptions options) : base(options)
{
}
}
public class Entity
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
I got it working by setting the InMemoryDatabaseRoot to the same object on all contexts.
private InMemoryDatabaseRoot _root;
private InMemoryDatabaseRoot Root
{
get
{
if(_root == null)
_root = new InMemoryDatabaseRoot();
return _root;
}
}
[Test]
public void MultipleContextTest()
{
var firstContext = new FirstContext(CreateOptions<FirstContext>());
firstContext.Add(new Entity() {Name = "Test"});
firstContext.SaveChanges();
var secondContext = new SecondContext(CreateOptions<SecondContext>());
Assert.AreEqual(firstContext.Entity.Count(), secondContext.Entity.Count());
}
private DbContextOptions CreateOptions<T>() where T : DbContext
{
return new DbContextOptionsBuilder<T>()
.UseInMemoryDatabase("DB", Root)
.Options;
}

Maping generic interface to concreate class but using interface definition -> automapper

Hey I'm trying to map my generic class to concrete class but using it's interface.
My service returns me data which type is
IPaggedResults<Customer>
and I want to be able to map this to
IPaggedResults<CustomerDto>
It works if I invoke mapping with:
_mapper.Map<PaggedResults<CustomerDto>>
but I want use following syntax:
_mapper.Map<IPaggedResults<CustomerDto>>
public class PaggedResults<T> : IPaggedResults<T>
{
public IEnumerable<T> Results { get; protected set; }
public int TotalResults { get; protected set; }
public int TotalPages { get; protected set; }
public int ResultsPerPage { get; protected set; }
public PaggedResults(IEnumerable<T> results, int totalResults, int resultsPerPage)
{
Results = results;
TotalResults = totalResults;
TotalPages = totalResults / resultsPerPage;
ResultsPerPage = resultsPerPage;
}
}
public class CustomerDto
{
public int Id { get; set; }
public string Name { get; set; }
public string NIP { get; set; }
}
My mapper configuration:
public static IMapper Initialize()
=> new MapperConfiguration(cfg =>
{
cfg.CreateMap<CustomerCompany, CustomerDto>();
cfg.CreateMap(typeof(IPaggedResults<>), typeof(PaggedResults<>));
cfg.CreateMap(typeof(IPaggedResults<>), typeof(IPaggedResults<>)).As(typeof(PaggedResults<>));
}).CreateMapper();
Im'using Automapper by Jimmy Bogard.
I could achieve it through the following code:
Create an extension for IMapperConfigurationExpression
public static class IMapperConfigurationExpressionExtensions
{
public static void MapPaggedResults<TSource, TDestination>(this IMapperConfigurationExpression exp){
exp.CreateMap(typeof(PaggedResults<TSource>), typeof(IPaggedResults<TDestination>))
.ConstructUsing((source, ctx) => { return ctx.Mapper.Map<PaggedResults<TDestination>>(source) as IPaggedResults<TDestination>; });
}
}
Then use this configuration:
public static IMapper Initialize()
=> new MapperConfiguration(cfg =>
{
cfg.CreateMap(typeof(IPaggedResults<>), typeof(PaggedResults<>));
cfg.MapPaggedResults<CustomerCompany, CustomerDto>();
}).CreateMapper();
Then both results can be obtained:
var _mapper = Initialize();
IPaggedResults<CustomerCompany> source = new PaggedResults<CustomerCompany>(
new List<CustomerCompany>() { new CustomerCompany() {Id =42, Name = "SomeName", NIP = "someNIP" } }, 1, 1);
var resut = _mapper.Map<PaggedResults<CustomerDto>>(source);
var resut2 = _mapper.Map<IPaggedResults<CustomerDto>>(source);

How do I setup this in Moq to give me null or an object?

I want to saw that I do not care what is in the Find clause. Just give me null.
Here is the test
[Fact]
public void VerifyIndexViewType()
{
// Arrange
var mockUserProvider = new Mock<IUserProvider>();
mockUserProvider.Setup(x => x.GetUserId()).Returns("any-value-here");
var mockUnitOfWork = new Mock<IUnitOfWork>();
//how would I just return an object or null for example.. this doesnt work
// mockUnitOfWork.Setup(x => x.UserProfileDataRepository.Find(u => u.ApplicationUserId == "any value here")).Returns((IRepository<UserProfileData>)null);
var controller = new ProfileController(mockUnitOfWork.Object, mockUserProvider.Object);
// Act
var result = controller.Update();
// Assert
Assert.IsType<ViewResult>(result);
}
For the following controller and action
public class ProfileController : BaseController
{
private IUnitOfWork _unitOfWork;
private readonly IUserProvider _requestUserProvider;
public ProfileController(IUnitOfWork unitOfWork,
IUserProvider requestUserProvider)
: base(unitOfWork, requestUserProvider)
{
_unitOfWork = unitOfWork;
_requestUserProvider = requestUserProvider;
}
public IActionResult Update()
{
//this is easy
string userId = _requestUserProvider.GetUserId();
//how do I do the setup in moq for this?
IEnumerable<UserProfileData> userProfileQuestions = _unitOfWork.UserProfileDataRepository.Find(x => x.ApplicationUserId == userId);
if (userProfileQuestions != null)
{
ProfileViewModel profileViewModel = new ProfileViewModel();
profileViewModel.UserProfileData = userProfileQuestions.FirstOrDefault();
return View(profileViewModel);
}
return View("Error", "Home");
}
EDIT 1: MY IUnitOfWork and implementation of the method
public interface IUnitOfWork
{
IRepository<ApplicationUser> ApplicationUserRepository { get; }
IRepository<RefMedicalSpecialty> RefMedicalSpecialtyRepository { get; }
IRepository<RefProgramDetailData> RefProgramDetailDataRepository { get; }
IRepository<RefProgramProfileData> ProgramProfileDataRepository { get; }
IRepository<UserProgram> UserProgramRepository { get; }
IRepository<UserFeedback> UserFeedbackRepository { get; }
IRepository<UserAction> UserActionRepository { get; }
IRepository<UserProfileData> UserProfileDataRepository { get; }
IRepository<RawCredential> RawCredentialRepository { get; }
IRepository<RefProgramCharacteristic> RefProgramCharacteristicRepository { get; }
IRepository<UserProgramRefProgramCharacteristic> UserProgramRefProgramCharacteristicRepository { get; }
void Commit();
void RejectChanges();
void Dispose();
}
public IRepository<UserProfileData> UserProfileDataRepository =>
new Repository<UserProfileData>(_retContext);
Declare the Method Find as virtual
public virtual YourType Find(Expression<Func<YourClass, bool>> yourfunc)
and the mock as:
mockUnitOfWork.Setup(x => x.UserProfileDataRepository.Find(It.IsAny<Expression<Func<YourClass, bool>>>()).Returns(DefineYourReturn);

Accessing Moq Mock Data from DbContext disappears when called twice?

I am trying to understand a behavior that is occurring in my application. I have mocked out my DbContext and when I make a call get items from the dbContext.Set<T>().ToList(), the second call does not contain my mocked data. I am not sure why this happens since that data should still exist. Please see code below:
SUT:
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public decimal Salary { get; set; }
}
public class EmployeeDb
: DbContext
{
public EmployeeDb()
{
}
public virtual IDbSet<Employee> Employees { get; set; }
}
UNIT TEST:
public class MockDatabase
{
public Mock<EmployeeDb> SetMockData()
{
var mockDb = new Mock<EmployeeDb>();
mockDb.Setup(i => i.Set<Employee>()).Returns(GetMockSet(Employees).Object);
mockDb.SetupGet(i => i.Employees).Returns(() => GetMockSet(Employees).Object);
return mockDb;
}
private List<Employee> _providers;
private List<Employee> Employees => _providers ?? (_providers = new List<Employee>
{
GetEmployee(1),
GetEmployee(2),
GetEmployee(3),
GetEmployee(4),
GetEmployee(5),
});
private static Employee GetEmployee(int id)
{
return new Employee
{
FirstName = Faker.Name.First(),
LastName = Faker.Name.Last(),
Age = Faker.RandomNumber.Next(50),
Id = id,
Salary = Faker.RandomNumber.Next(100000)
};
}
#region Hood
public static Mock<DbSet<T>> GetMockSet<T>(IList<T> items) where T : class
{
var querable = items.AsQueryable();
var mockSet = new Mock<DbSet<T>>();
mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(querable.Provider);
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(querable.Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(querable.ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(querable.GetEnumerator());
mockSet.Setup(i => i.Add(It.IsAny<T>())).Callback(delegate (T item) {
items.Add(item);
});
return mockSet;
}
#endregion
}
[TestClass]
public class UnitTest1
{
private EmployeeDb _context;
[TestInitialize]
public void TestInitialize()
{
var mockDb = new MockDatabase();
_context = mockDb.SetMockData().Object;
}
[TestMethod]
public void Test_CallTwice_ReturnsEqualCount()
{
var emps = _context.Set<Employee>().ToList();
var emps2 = _context.Set<Employee>().ToList();
Assert.IsTrue(emps.Count == emps2.Count);
// -- This works
//var empCount = _context.Set<Employee>().Count();
//var empCount2 = _context.Set<Employee>().Count();
//Assert.IsTrue(empCount == empCount2);
}
}
Is there something I am not getting about this code? Is there something Moq does with the ToList()?
ToList enumerates the set when invoked, but the enumerator is forward only, so after the first call it is already at the end.
When setting up the GetEnumerator use the function overload of the Returns in order to allow multiple calls other wise the same enumerator will be returned every time and you get the behavior you experienced.
mockSet.As<IQueryable<T>>()
.Setup(m => m.GetEnumerator())
.Returns(() => querable.GetEnumerator()); //<-- function

is it a good practice to pass an EF DbContext as delegate in services to attach all changes on it

Having the following context:
public class DemoContext : DbContext
{
private readonly string _connectionStringName = "DemoContext";
public DemoContext() : base("name=DemoContext")
{
//_connectionStringName = "DemoContext";
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
//Database.SetInitializer(new MigrateDatabaseToLatestVersion<DemoContext, Migrations.Configuration>(_connectionStringName));
Database.SetInitializer(new NullDatabaseInitializer<DemoContext>());
}
public DbSet<Employee> Employees { get; set; }
public DbSet<Company> Companies { get; set; }
}
public class Employee
{
[Key]
public int EmployeeId { get; set; }
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class Company
{
[Key]
public int CompanyId { get; set; }
public string CompanyName { get; set; }
}
And this services:
public class EmployeeSvc
{
private readonly DemoContext _context;
public EmployeeSvc(Func<DemoContext> context)
{
_context = context();
}
public void Add(EmployeeAgg employee)
{
_context.Employees.Attach(new Employee()
{
Name = employee.Name,
DateOfBirth = employee.DateOfBirth
});
}
public void UpdateAll()
{
var employees = _context.Employees.ToList();
foreach (var employee in employees)
{
employee.Name = $"{Guid.NewGuid()}";
}
}
}
public class CompanySvc
{
private readonly DemoContext _context;
public CompanySvc(Func<DemoContext> context)
{
_context = context();
}
public void Add(CompanyAgg company)
{
_context.Companies.Attach(new Company()
{
CompanyName = company.CompanyName
});
}
public void UpdateAll()
{
var empresas = _context.Companies.ToList();
foreach (var empresa in empresas)
{
empresa.CompanyName = $"{Guid.NewGuid()}";
}
}
}
public class EmployeeAgg
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class CompanyAgg
{
public string CompanyName { get; set; }
}
Anf the following client code:
static void Main(string[] args)
{
var context = new DemoContext();
// ReSharper disable AccessToDisposedClosure
var employeeSvc = new EmployeeSvc(() => context);
var companySvc = new CompanySvc(() => context);
// ReSharper restore AccessToDisposedClosure
Console.WriteLine("Adding entities to context inside services");
employeeSvc.Add(new EmployeeAgg()
{
DateOfBirth = DateTime.Now.AddYears(-10),
Name = $"Employee name"
});
companySvc.Add(new CompanyAgg()
{
CompanyName = $"Company name"
});
employeeSvc.UpdateAll();
companySvc.UpdateAll();
context.SaveChanges();
context.Dispose();
Console.ReadLine();
}
Is it a good practice passing DbContext to application services as delegate in order to have a reference to a single instance and track all changes on it?
Maybe it's your example code, but there's no need here to use a delegate. You could as well just accept a DbContext and pass in the same instance:
public class EmployeeSvc
{
private readonly DemoContext _context;
public EmployeeSvc(DemoContext context)
{
_context = context();
}
// snip ...
}
public class CompanySvc
{
private readonly DemoContext _context;
public CompanySvc(DemoContext context)
{
_context = context();
}
// snip ...
}
var context = new DemoContext();
var employeeSvc = new EmployeeSvc(context);
var companySvc = new CompanySvc(context);
This would give you the exact same result, without needing to pass in a delegate and immediately invoking it.
I suppose however that maybe your actual code is a bit more complicated. If so, you should look into dependency injection and a DI-container.
A DI-container allows you to manage your dependencies and their lifecycles. A common lifecycle is the Singleton lifecycle, where the container will always construct your dependencies passing in the same instance.
if you need to injection your dbContext is better to use interface.
func<> is not suitable.
in Dependency injection interface is suitable.
(excusme for bad english)

Categories

Resources