How to setup Mocked context using Moq? - c#

I have implemented a Repository Pattern using an onion Architecture and Entity Framework for Data Access, and now I want to test it using Moq. I just asked a question on SO and with the answer I am now more confused (the answer was good but I have very poor comprehension of how to mock even after reading doc). What I want to do is test Repository method Get(long id). My repository constructor takes a DbContext as parameter(called PrincipalServerContext, so I was suggested to mock the context in order to test my Repository. Let's say this is my Repository:
public class PrincipalServerContext : DbContext
{
public DbSet<Web_Documents> WebDoc { get; set; }
public PrincipalServerContext()
: base("name=PrincipalServerDB")
{
Database.SetInitializer(new Initializer());
}
}
Now one of my POCOs Web_Documents (EF entity):
public class Web_Documents
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long IDDocument { get; set; }
[Required]
[MaxLength(255)]
public string NomDocument { get; set; }
[Required]
public long IDCategorie { get; set; }
[ForeignKey("IDCategorie")]
public Web_Categories cat { get; set; }
[Required]
[MaxLength(255)]
public string Lien { get; set; }
[MaxLength(50)]
public string Type { get; set; }
public virtual ICollection<Web_Profils> Profils { get; set; }
}
And finally my Repository method (knowing that repository is generic, I use POCOs as Generic Types):
public T Get(long id)
{
ObjectContext objContext = ((IObjectContextAdapter)context).ObjectContext;
ObjectSet<T> set = objContext.CreateObjectSet<T>();
IEnumerable<string> keyNames = set.EntitySet.ElementType
.KeyMembers
.Select(k => k.Name);
if (keyNames.Count() > 1)
return null;
else
{
string idName = keyNames.ElementAt(0); // For Document would be IDDocument
var parameter = Expression.Parameter(typeof(T));
var property = Expression.Property(parameter, idName);
var idValue = Expression.Constant(id, id.GetType());
var equal = Expression.Equal(property, idValue);
var predicate = Expression.Lambda<Func<T, bool>>(equal, parameter);
return entities.SingleOrDefault(predicate);
//Returns the corresponding entity to 'id' and 'T'
}
}
This builds an expression with appropriate ID names because every table has a different ID Name (company's policy).
From what I was told here Should this case of Assert.AreSame return true? I understand that I have to build a return type for the Mock object, but my context class is so thin I don't have any methods or anything, just a DbSet.
So I tried this as a test but it probably makes no sense since it failed (I'm just really lost and don't understand it):
Mock<PrincipalServerContext> moqContext;
public void IdExists(){
moqContext = new Mock<PrincipalServerContext>();
var set = new Mock<DbSet<Web_Documents>>();
moqContext.Setup(c => c.Set<Web_Documents>()).Returns(set.Object);
repoDoc = new Repository<Web_Documents>(moqContext.Object);
var testDoc = repoDoc.Get(1L);
Assert.AreEqual(testDoc.NomDocument, "Ajouter une catégorie");
}
Say I would want to make a simple test to find if the ID searched corresponds to my DB entry, how should I set the moqContext object I am trying to define? In examples I see they usually have methods for their mocked objects, but here none, so I found this Mocking DbContext for TDD Repository which made me try this test.
Thanks for your help!

Here's an example of using the in-memory database.
First you create an request an instance of the mock unit of work.
[TestMethod]
public async Task ExampleTest() {
//arrange
Mock<IUnitOfWork> mockUow = MockUowFactory.Get(nameof(ExampleTest));
//act
using (var app = YOURAPP(mockUow.Object)){
app.METHODUNDERTEST();
}
//assert
...
}
Then you build up the mock unit of work. According to what I've read the separate context is needed (one for seeding, one for testing). The MockEntityFactory just returns an array of dummy data which is used to populate the dbsets in our InMemoryDatabase.
public class MockUowFactory {
public static Mock<IUnitOfWork> Get(string dbName) {
DbContextOptions<YOUR CONTEXT> options = new DbContextOptionsBuilder<YOUR CONTEXT>()
.UseInMemoryDatabase(databaseName: dbName)
.Options;
using (var seedContext = new YOURCONTEXT(options)) {
seedContext.YOURENTITY.AddRange(MockEntityFactory.YOURENTITY);
seedContext.SaveChanges();
}
var context = new YOURCONTEXT(options);
var mockUow = new Mock<IUnitOfWork>();
mockUow.Setup(m => m.Context).Returns(context);
mockUow.Setup(m => m.Save()).Returns(() => context.SaveChanges().ToString());
return mockUow;
}
}
I then pass this unit of work through the necessary layers and don't need to do anything special to test my production code.

Related

Writing a unit test for a Builder Class

I am writing a project that takes a JSON file to deserialize it and Build the data and process them then save it to the database. Now I want to write a unit test using Mock for this class but I don't know how to do this because in this method I only equalize the field in my DTO and database
this is my order Dto
public class OrderDto
{
public int Code { get; set; }
public int CustomerCode { get; set; }
public int StoreCode { get; set; }
public string OrderDate { get; set; }
public string OrderStatus { get; set; }
public string DeliveryDate { get; set; }
}
This is my order builder class
public class OrderBuilder
{
static PracticeEntities _context;
public OrderBuilder(PracticeEntities4 context)
{
_context = context;
}
public static CustomersOrder OrderBuild(OrderDto dto)
{
//using (var context = new PracticeEntities4())
//{
var oldStoreId = _context.Stores.FirstOrDefault(e => e.Code == dto.StoreCode).Id;
var oldCustomerId = _context.Customers.FirstOrDefault(e => e.Code == dto.CustomerCode).Id;
return new CustomersOrder()
{
OrderDate = Convert.ToDateTime(dto.OrderDate),
OrderStatus = dto.OrderStatus,
DeliveryDate = Convert.ToDateTime(dto.DeliveryDate),
CustomerId = oldCustomerId,
StoreId = oldStoreId,
Code = dto.Code
};
//};
}
}
UPDATED
First thing to note is that a static class can't be unit tested. So the method to be tested shall be modified as such below shown. Also, the dbcontext i.e. IPracticeEntities4 interface which is implemented in the PracticeEntities4 class need to be injected so that it can be mocked.
public class PracticeEntities4:IPracticeEntities4, DbContext
{
....
}
public class ClassMethod2BTested
{
IPracticeEntities4 _context; //declare the context
public ClassMethod2BTested(IPracticeEntities4 context) // inject the context
{
_context=context; // set the context to local variable
}
public CustomersOrder OrderBuild(OrderDto dto)
{
//using (var context = new PracticeEntities4()) // remove this
{
var oldStoreId = _context.Stores.FirstOrDefault(e => e.Code == dto.StoreCode).Id;
var oldCustomerId = _context.Customers.FirstOrDefault(e => e.Code dto.CustomerCode).Id;
return new CustomersOrder()
{
OrderDate = Convert.ToDateTime(dto.OrderDate),
OrderStatus = dto.OrderStatus,
DeliveryDate = Convert.ToDateTime(dto.DeliveryDate),
CustomerId = oldCustomerId,
StoreId = oldStoreId,
Code = dto.Code
};
};
}
}
Now the above method can be united tested.
For unit test, Please check the sample here: Mocking EF DbContext with Moq
Added
Please check this code:
github
Since you are using entity framework, I think this article will help you: https://learn.microsoft.com/en-us/ef/ef6/fundamentals/testing/mocking
Create your own test doubles – This approach involves writing your own in-memory implementation of your context and DbSets. This gives you a lot of control over how the classes behave but can involve writing and owning a reasonable amount of code.
Use a mocking framework to create test doubles – Using a mocking framework (such as Moq) you can have the in-memory implementations of your context and sets created dynamically at runtime for you.
So with the first way you can simulate a db call with specific data and make sure the result returns successfully.
These tests, while not securing business errors protect your code from missing null checks and runtime errors like that.

C# Entity Framework (Code first), Implementing CRUD Operations on Model

I just wondering if you can store a function in a model (CRUD transactions)
that will look something like this:
My Existing code:
public class tbluser
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int id { get; set; }
[Required(ErrorMessage = "Username is required")]
public string username { get; set; }
[Required(ErrorMessage = "Password is required")]
public string password { get; set; }
public static List<tbluser> list()
{
using (var db = new sample())
{
var user = db.tbluser.ToList();
return user;
}
}
}
What i want:
public class tbluser:DbContext
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int id { get; set; }
[Required(ErrorMessage = "Username is required")]
public string username { get; set; }
[Required(ErrorMessage = "Password is required")]
public string password { get; set; }
public static List<tbluser> list()
{
return this.toList();
}
}
I just want to ask also if that method of implementing Entity Framework is ok.
Here is a quick example of how you might setup a simple Code First implementation to get started.
First, define your User model. The Key attribute on an integer type automatically configures the identity property for you. Then, you may want an index on username if you plan to do frequent lookups by username (to get user details or to validate a password).
public class User
{
[Key] // Becomes identity by default
public int Id { get; set; }
[Index("IX_User_Username", IsUnique = true)]
public string Username { get; set; }
public string Password { get; set; }
}
Then, you can define
public class AppDataContext : DbContext
{
public AppDataContext() : base("name=DBConnection") { }
public DbSet<User> Users { get; set; }
}
You will just need to be sure there is a connection string in your config file to match the name passed there.
<connectionStrings>
<add name="DBConnection" providerName="System.Data.SqlClient"
connectionString="Data Source=instancePath;Initial Catalog=dbName;Integrated Security=true;MultipleActiveResultSets=True" />
</connectionStrings>
This would now allow you to create repos such as this:
public class UserRepo : IDisposable
{
public Lazy<AppDataContext> _db = new Lazy<AppDataContext>(() => new AppDataContext());
public IQueryable<User> Get() => _db.Value.Users.AsQueryable();
public IList<User> GetAll() => _db.Value.Users.ToList();
public void Dispose()
{
if (_db.IsValueCreated)
_db.Value.Dispose();
}
}
So then you can either use the repo or the context directly.
// Use the repo
using (var userRepo = new UserRepo())
{
var allUsers = userRepo.GetAll();
var user = userRepo.Get().FirstOrDefault(m => m.Username == "myUsername");
}
// Or just use the data context
using (var db = new AppDataContext())
{
var allUsers = db.Users.ToList(); // Get all users
var user = db.Users.FirstOrDefault(m => m.Username == "myUsername");
}
For more information, here are some useful links with great details:
Simple Example
Data Annotations
Initializer Config
Migrations
Code like this is going to be heavily problematic.
In the first example you are tightly coupling an instance of a DbContext to an entity. Calling tblUser.list() will return a list of User entities, but these will now be outside of the scope of a DbContext. (Due to the using() block closure) This means that any lazy load calls to retrieve related entities will fail and you cannot persist any changes to the entities until they are re-attached to another DbContext. This gets very messy, very fast.
In the second example you would be extending a DbContext, meaning each "entity" is effectively scoping a DbContext use to populate instances of itself. You can't just "static" wrap the method because that wouldn't have visibility to the non-static DbSets inherited from DbContext.
This would be horrible in terms of performance, and from a code perspective would look plain weird:
I.e.
using (var user = new tbluser)
{
var users = user.list(); // not static.
// .. Do stuff..
}
To make it static would be problematic because a DbContext would need to be static-scoped inside tbluser
public class tbluser
{
private static MyContext _context = new MyContext();
// ...
public static List<tbluser> list()
{
return _context.tblusers.ToList();
}
}
And this may still have issues, such as how the static instance is disposed, before it was remotely functional but I certainly cannot recommend an approach like this.
Instead, use the DbContext as it is intended. Look at IoC containers like Unity or Autofac to manage the lifetime scope for for the DbContext and inject an instance as a dependency into classes that need it, or at a minimum wrap it in a using() {} block and treat it like an repository with it's DbSets.
There are lots of examples of using the DbContext effectively, using Repositories and Unit of Work patterns with dependency injection. Master these before attempting to spin up something unique. Future developers looking at your code will thank you. :)
There is one famous principle called "Separation of Concerns" that will get very angry if you do this. My advice is to keep the code simple, meaningful and loosely coupled.

Reflection on mocked data in unit tests (Rhino)

I have some code that selects a property using reflection. It works fine but I can't unit test it. Apparently, the mock that it creates does not have any properties.
Can anyone tell me how to get the property from a Mocked object using reflection? (Or explain why it would not be possible?)
var target = To.GetType().GetProperties()
.Single(x => typeof(IRepository<T>).IsAssignableFrom(x.PropertyType))
.GetValue(To) as IRepository<T>;
I'm using this for a copy class which allows to copy data for any entity type and expects a UnitOfWork that contains a IRepository where T is the type that you want to copy.
public class TableCopier<T> : ICopier where T : EntityBase
{
public IUnitOfWork From { get; set; }
public IUnitOfWork To { get; set; }
public virtual int Copy(IProgressReporter progres = null)
{
lock (this)
{
var target = To.GetType().GetProperties()
.Single(x => typeof(IRepository<T>).IsAssignableFrom(x.PropertyType))
.GetValue(To) as IRepository<T>;
//...
}
}
}
The Unit of Work looks like this:
public interface IUnitOfWork
{
IRepository<Parameter> ParameterRepository { get; }
IRepository<Company> CompanyRepository { get; }
IRepository<CompanyAccountancynumber> CompanyAccountancynumberRepository { get; }
//...
And finally the unit test:
[Test]
public void DefaultCopy()
{
// (removed some code)
var to = MockRepository.GenerateStrictMock<IUnitOfWork>();
var target = MockRepository.GenerateStrictMock<IRepository<CompanyDataset>>();
to.Stub(x => x.CompanyDatasetRepository).Return(target);
var inserted = new List<CompanyDataset>();
target.Stub(x => x.BulkInsert(null))
.IgnoreArguments()
.WhenCalled(x => inserted.AddRange(x.Arguments[0] as IEnumerable<CompanyDataset>));
//ACT
var copier = new TableCopier<CompanyDataset>() as ICopier;
copier.Copy(from, to, map, log, null, CancellationToken.None );
I found the problem:
The properties are available as explicit properties.
And to access these kind of properties you need the interface map.
This means I should change this:
var target = To.GetType().GetProperties()
.Single(x => typeof(IRepository<T>).IsAssignableFrom(x.PropertyType))
.GetValue(To) as IRepository<T>;
To this:
var target = To.GetType().GetInterfaceMap(typeof(IUnitOfWork))
.InterfaceMethods
.Single(x => (typeof(IRepository<T>).IsAssignableFrom(x.ReturnType)))
.Invoke(To, null) as IRepository<T>;
My own implementations of IUnitOfWork used 'implicit' properties, so that explains why that worked and the unit test failed. Also using the map is generally better (/more correct) (-> no chance on problems if I would ever make another implementation of the interface with explicit props). So I suppose it was a good unit test :)
Regards

Setting property value on child instance to a fixed value with Autofixture

Is it possible to assign a fixed value to a property on a child instance when building a parent with Autofixture? It will add default values to all the properties on the child instance like a charm, but I would like to override and assign a specific value to one of the properties on the child instance.
Given this parent/child relationship:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Street { get; set; }
public int Number { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
}
I would like to assign a specific value to the City property on the address instance. I was thinking in the lines of this test code:
var fixture = new Fixture();
var expectedCity = "foo";
var person = fixture
.Build<Person>()
.With(x => x.Address.City, expectedCity)
.Create();
Assert.AreEqual(expectedCity, person.Address.City);
That is not possible. I guess, by the reflection exception
System.Reflection.TargetException : Object does not match target type.
...that Autofixture tries to assign the value to a City property on the Person instance instead of an Address instance.
Any suggestions?
And yes, I know that I could just add an extra step like the following:
var fixture = new Fixture();
var expectedCity = "foo";
// extra step begin
var address = fixture
.Build<Address>()
.With(x => x.City, expectedCity)
.Create();
// extra step end
var person = fixture
.Build<Person>()
.With(x => x.Address, address)
.Create();
Assert.AreEqual(expectedCity, person.Address.City);
...but was hoping for the first version or something similar (fewer steps, more terse).
Note: I'm using Autofixture v3.22.0
For completeness, here's another way to do it:
fixture.Customize<Address>(c =>
c.With(addr => addr.City, "foo"));
var person = fixture.Create<Person>();
This will customize the creation of all instances of Address
If you end up using this often enough, it may be worthwhile wrapping it inside an ICustomization:
public class AddressConventions : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<Address>(c =>
c.With(addr => addr.City, "foo"));
}
}
fixture.Customize(new AddressConventions());
Not to be dismissive of the question, but the simplest solution might actually be this:
[Fact]
public void SimplestThingThatCouldPossiblyWork()
{
var fixture = new Fixture();
var expectedCity = "foo";
var person = fixture.Create<Person>();
person.Address.City = expectedCity;
Assert.Equal(expectedCity, person.Address.City);
}
Assignment of explicit values to properties is something most languages already excel at (C# certainly does), so I don't think AutoFixture needs a complicated DSL to reproduce half of that functionality.
You can use a Do method on the builder:
var person = this.fixture
.Build<Person>()
.Do( x => x.Address.City = expectedCity )
.Create();
You can also inject and freeze your instance to the fixture:
this.fixture.Inject( expectedCity );

How do I get the .ToList to show when reading from a repository...Where am I going wrong?

For some reason, C# wont show me the .ToList on my code. I am wondering how to get it.
I have a basic MVC4 app which I successfully divided into several projects as a proof of concept. So here are my layers...Everything works until I try to add a domain layer. This is where the confusion starts. So some code:
My model is generated from the database by EF5. I have a standard "Student" class with an ID and a Name. This is all. It relates to a course. A course has many students. Here is what EF Generates.
public partial class Student
{
public int Id { get; set; }
public Nullable<int> CourseId { get; set; }
public string Name { get; set; }
public Nullable<System.DateTime> DateAttended { get; set; } //This field becomes important later
public virtual Course Course { get; set; }
}
Here is the course model.
public partial class Course
{
public Course()
{
this.Student = new HashSet<Student>();
}
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Student> Student { get; set; }
}
I extracted this out to a Models project and fully tested everything after. All went well, no problems there.
Then I added a generic repo layer between this and my controller to remove the DB access logic from my controllers. Here is the interface:
public interface IHeadRepository<TEntity>
{
ICollection<TEntity> ReadAll(); //I Want to focus here for the problem...
int Create(TEntity entity);
TEntity ReadSingle(int id);
ICollection<TEntity> ReadSome(Expression<Func<TEntity, bool>> predicate);
int Update(TEntity entity);
int Delete(TEntity entity);
}
I will only show the implementation of the part I want to focus on for brevity...
public class HeadRepo<TEntity> : IHeadRepository<TEntity> where TEntity : class
{
protected DbSet<TEntity> dbSet;
private readonly DbContext dbContext;
public HeadRepo() { }
public HeadRepo(DbContext dbContext)
{
this.dbContext = dbContext;
dbSet = dbContext.Set<TEntity>();
}
public ICollection<TEntity> ReadAll()
{
return dbSet.ToList();
}
}
Before I started trying to implement my domain layer, I tested everything and it all worked. So I proceeded to implement my domain layer and made a few changes to my repo.
Origionally both the interface and repo looked like this...
public IQueryable<TEntity> ReadAll()
{
return dbSet;
}
It was an Iqueriable instead of a ICollection. I tried all kinds of changes, IList, IEnumerable etc.
Finally...The problem I am having seems to be with my controller...But I am aware that it could be because of the way I implemented the repo. However I don't know how to fix it.
So here is my controller...The index action.
This is the before. It worked fine.:
public ActionResult Index()
{
return View(studentRepo.ReadAll());
}
What I am trying to do (and I know I could do this simple task in any number of places but I want to get it working here and extract it later) is add a ViewModel which has an extra field called something like YearsGraduated. Like this:
public class StudentVM : Student
{
[Display(Name = "Years Graduated:")]
public int YearsGraduated { get; set; }
}
Then I want to go to my controller and, use my repo to read all the students, assign the list of students to my list of studentVM's and then run a simple method on them to calculate the years since they graduated. So here it is in SemiSudo...
public ActionResult Index()
{
//I get an error when I do this (the best overloaded...has invalid args)
//var vm = new List<StudentVM>(studentRepo.ReadAll());
//So I try this:
//var vm = new List<StudentVM>();
//vm = studentRepo.ReadAll(); //I get error here...Cannot implicity comvert...explisit exists
//So I try this:
//var vm = new List<StudentVM>();
//vm = studentRepo.ReadAll().ToList(); //I get error here...No definition / extension method .ToList() can be found
//So I tried updating my repo interface and changing it from:
//IQueriable to ICollection
//ICollection to IEnumerable
//IEnumerable to IList
//IList to List
//Without any success.
//As explained, if I can get this working, I would like to do something like:
//
//var vm = new List<StudentVM>();
//vm = studentRepo.ReadAll();
//For(i=0; i<vm.count; i++)
//{
// vm[i].YearsGraduated = CalcYearsExpired(vm[i].DateAttended)
//}
//Some method outside this called CalcYearsExpired() which takes a date,
//returns an int or double and im done.
//Then the return method changes from this:
//return View(studentRepo.ReadAll());
//To something like this:
//return View("Index", vm);
//And the view changes accordingly to use the Collection<StudentVM> to list the students.
}
Any help would be greatly appreciated...My goal would be to add a domain layer and extract this code when working so my controller stays simple. I am having great difficulty doing this so obviously there is no point in trying to do it elsewhere if I cant do it locally in the controller or repo first. I don't want to put it into the repo because it will make the repo to specific and I want to try keep it generic. But my priority is to resolve the problem so if I have to make the repo more specific I would.
Include the namespace System.Linq if not?

Categories

Resources