Writing a unit test for a Builder Class - c#

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.

Related

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.

How to setup Mocked context using Moq?

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.

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

Can't find objects which reference entity framework entity

I'm running into an InvalidOperationException because "An entity object cannot be referenced by multiple instances of IEntityChangeTracker." on the first line of EntityFrameWorkRepository.Create().
I know this is due to having multiple database contexts, but in this case I'm a bit lost as the code has no obvious second context since all database access goes through a designated object whose sole purpose is managing database contexts. This was done as the web application in question is fairly interactive and so the user is constantly creating new objects which must be saved in the database. This was causing issues with the previous design, which used locking and a single context, thus the code was refactored and works, except for the method in question.
EF class:
public class EntityFrameWorkRepository<TKey, TEntity> : IDisposable, IRepository<TKey,TEntity> where TEntity: class
{
private readonly IDbContext _context;
private IDbSet<TEntity> _entities;
public EntityFrameWorkRepository()
{
_context = new ApplicationDbContext();
}
private IDbSet<TEntity> Entities
{
get { return _entities ?? (_entities = _context.Set<TEntity>()); }
}
public void Create(TEntity entity)
{
Entities.Add(entity);
_context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
The service object used for all DB access:
public class Service : IService
{
public const string Persistance = "Persist";
public const int CacheTaskSeconds = 300; //Check every 5 minutes
public const double IdleMinutes = 30.0;
private readonly IKvpRepository<int, SimulationCollection> _simulationCollectionAppStateRepository;
private readonly UserManager<ApplicationUser> _userManager;
public Service(IKvpRepository<int, SimulationCollection> simulationCollectionAppStateRepository)
{
_userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
AddTaskToCache(Persistance, CacheTaskSeconds);
}
public SimulationCollection CreateCollection(Guid userId, string name, string description)
{
using (var _simulationCollectionEFRepository = new EntityFrameWorkRepository<int, SimulationCollectionEntity>())
{
var applicationUser = _userManager.FindById(userId.ToString());
if (applicationUser == null)
throw new ArgumentOutOfRangeException("ApplicationUser matching userId doesn't exist");
var collectionEntity = new SimulationCollectionEntity(applicationUser, name, description);
_simulationCollectionEFRepository.Create(collectionEntity);
return collection;
}
}
}
The object I'm trying to add to the database:
public class SimulationCollectionEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int Id { get; set; }
public string Name { get; set; }
public virtual ApplicationUser User { get; set; }
public DateTime DateCreated { get; set; }
public string Description { get; set; }
[ForeignKey("SimulationCollectionEntityId")]
public virtual ICollection<SimulationEntity> Simulations { get; set; }
[Obsolete("Only needed for serialization and materialization", true)]
public SimulationCollectionEntity() {}
public SimulationCollectionEntity(ApplicationUser currentUser, string name, string description)
{
User = currentUser;
Name = name;
Description = description;
DateCreated = DateTime.Now;
}
}
Is there an easy way to view what contexts a given object might be attached to? I already checked to see if collectionEntity is attached to _userManager since it has a dbContext, but its state is detached. Does EF maybe expect me to add objects in a different way than I am? I suspect that the attributes in SimulationCollectionEntity might be causing me trouble but I'm new to Entity Framework and I'm not sure. Should I maybe be going for a different design instead like this?
You might want to consider a unit of work like approach where one context is shared among multiple repositories. The accepted answer for this post is a good example. I have seen ContextPerRequest solutions like the one in your example, but I've never been crazy about them. Ideally you want a short lived context that does one thing like add an invoice and two invoice items - a single unit of work. You could then wrap the whole operation in a TransactionScope and have it succeed or fail as a unit.

Custom key generation in RavenDB

I have sets of entities all of them are derived from abstract class
public abstract class NamedEntity : INamedEntity
{
#region Public Properties
public string Description { get; set; }
public string Id { get; set; }
public string Name { get; set; }
#endregion
}
When I persist all entities I want to use Name field as a key, so I override DocumentKeyGenerator and provide such implementation:
store.Conventions.DocumentKeyGenerator = entity =>
{
var namedEntity = entity as NamedEntity;
if (namedEntity != null)
{
return string.Format("{0}/{1}", store.Conventions.GetTypeTagName(entity.GetType()), namedEntity.Name);
}
return string.Format("{0}/", store.Conventions.GetTypeTagName(entity.GetType()));
};
It works fine when I persist the list of entities for the first time, but if I want to persist them again I get an exception
PUT attempted on document 'xxxxx' using a non current etag
I just started using RavenDB, so I cannot understand what I am doing wrong?
Just a guess, but it's probably not with your key generation, but how you are storing them.
On first usage you probably have something like:
var myEntity = new MyEntity(...);
session.Store(myEntity);
...
session.SaveChanges();
That part is fine, but on subsequent usage, you should not be doing the same thing. Instead, it should be more like this:
var myEntity = session.Load<MyEntity>("myentities/foobar");
myEntity.Something = 123;
...
session.SaveChanges();
Note there is no call to .Store() when making changes. This is because the entity is "tracked" by the session, and all changes to it are automatically persisted when you call .SaveChanges()

Categories

Resources