I designing an applications which basically has 3 different logic layers:
DB connector (implemented by ADO.NET).
BL the business logic (the only thing the UI knows).
DB repositories (connects between the first two).
The DB repositories are separated into sections of dependency and every final entity is polymorphic to one interface. In some cases there are dependencies between objects inside the same dependency sections - ISectionFactory (hence dependent).
In practice the BL is going to ask for an object of specific type (such as IngrediantType in my example) from the MainFactory (which is a factor for all the DB)
Because of this design I am forced to cast types on the UI - which obviously is a drag.
How can I change the design ?
Here is a brief look of design:
public class MainFactory
{
private Dictionary<Type, ISectionFactory> m_SectionsFactories;
private ISectionFactory treatmentsSectionFactory =
new TreatmentsSectionFactory();
public MainFactory()
{
m_SectionsFactories = new Dictionary<Type, ISectionFactory>
{
{typeof(IngrediantType),treatmentsSectionFactory}
};
}
public IConcreteDataCollection GetConcreteData(Type i_EntitiesName)
{
return m_SectionsFactories[i_EntitiesName]
.GetConcreteData(i_EntitiesName);
}
}
internal interface ISectionFactory
{
IConcreteDataCollection GetConcreteData(Type i_EntitiesName);
}
public class TreatmentsSectionFactory : ISectionFactory
{
private Dictionary<Type, IConcreteDataCollection>
m_ConcreteDataCollections;
private IngrediantTypes m_IngrediantTypes = new IngrediantTypes();
private Ingrediants m_Ingrediants = new Ingrediants();
public TreatmentsSectionFactory()
{
m_ConcreteDataCollections =
new Dictionary<Type, IConcreteDataCollection>();
m_ConcreteDataCollections
.Add(typeof(IngrediantType), m_IngrediantTypes);
m_ConcreteDataCollections
.Add(typeof(Ingrediants), m_Ingrediants);
}
public IConcreteDataCollection GetConcreteData(Type i_EntitiesName)
{
return m_ConcreteDataCollections[i_EntitiesName];
}
}
public interface IConcreteDataCollection : IEnumerable
{
// Iteratable.
IConcreteData GetById(int i_Id);
void AddNewConcreteData(IConcreteData i_ConcreteData);
void UppdateConcreteData(IConcreteData i_ConcreteData);
void DeleteConcreteData(IConcreteData i_ConcreteToDelete);
}
public class IngrediantTypes : IConcreteDataCollection
{
public string TestType { get; set; }
public IConcreteData GetById(int i_Id){}
public void AddNewConcreteData(IConcreteData i_ConcreteData){}
public void UppdateConcreteData(IConcreteData i_ConcreteData){}
public void DeleteConcreteData(IConcreteData i_ConcreteToDelete){}
public IEnumerator GetEnumerator(){}
}
// also implements IConcreteDataCollection
public class Ingrediants : IConcreteDataCollection
{
}
public interface IConcreteData
{
public int Index { set; get; }
} // the final (highest) entity of all DB entities
public class IngrediantType : IConcreteData
{
public int Index { set; get; }
// other set of properties
}
public class Ingrediant : IConcreteData
{
public int Index { set; get; }
public IngrediantType RelatedIngrediantType { set; get; }
// other set of properties
}
public class mainClass
{
public static void main()
{
MainFactory factory = new MainFactory();
var type = typeof(IngrediantType);
// returns a IngrdiantTypes of type (IConcreteDataCollection)
var t = factory.GetConcreteData(typeof(IngrediantType));
// I want to use the IngrediantType without casting !!!
var s = t.GetById(2);
}
}
It's a little hard to tell what's going on here, but I think the key will be to take advantage of generics like so:
public IConcreteDataCollection<T> GetConcreteData<T>()
{
return ...;
}
If I understand your question correctly, this will allow you to say:
var t = factory.GetConcreteData<IngrediantType>();
You will need to change almost every class in your code to use generics.
Related
Is it possible in DryIoc container to figure out whether some singleton has been instantiated?
For instance
var container = new Container();
container.Register<IApplicationContext, ApplicationContext>( Reuse.Singleton );
// var context = container.Resolve<IApplicationContext>();
if ( container.IsInstantiated<IApplicationContext>() ) // Apparently this does not compile
{
// ...
}
// OR
if ( container.IsInstantiated<ApplicationContext>() )
{
// ...
}
There is no way at the moment and no such feature planned. You may create an issue to request this.
But I am wandering why it is needed. Cause singleton provides a guarantee to be created only once, so you may not worry or check for double creation.
Is it for something else?
Update
OK, in DryIoc you may register a "decorator" to control and provide information about decoratee creation, here is more on decorators:
[TestFixture]
public class SO_IsInstantiatedViaDecorator
{
[Test]
public void Test()
{
var c = new Container();
c.Register<IService, X>(Reuse.Singleton);
c.Register<XProvider>(Reuse.Singleton);
c.Register<IService>(
Made.Of(_ => ServiceInfo.Of<XProvider>(), p => p.Create(Arg.Of<Func<IService>>())),
Reuse.Singleton,
Setup.Decorator);
c.Register<A>();
var x = c.Resolve<XProvider>();
Assert.IsFalse(x.IsCreated);
c.Resolve<A>();
Assert.IsTrue(x.IsCreated);
}
public interface IService { }
public class X : IService { }
public class A
{
public A(IService service) { }
}
public class XProvider
{
public bool IsCreated { get; private set; }
public IService Create(Func<IService> factory)
{
IsCreated = true;
return factory();
}
}
}
This example also illustrates how powerful is composition of DryIoc decorators and factory methods.
I'm new to Xunit and AutoFixture, and writing a theory that looks like:
[Theory, AutoData]
public void Some_Unit_Test(List<MyClass> data)
{
// Test stuff
}
MyClass looks like:
public class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
}
This causes AutoFixture to create a list of items with random values for each property. This is great, but I would like the IsActive property to always be true.
I could set it to true at the start of every test but I'm guessing there is a smarter way. I looked at InlineData, ClassData, PropertyData, even Inject() but nothing quite seemed to fit.
How can I improve this?
Here is one way to do this:
public class Test
{
[Theory, TestConventions]
public void ATestMethod(List<MyClass> data)
{
Assert.True(data.All(x => x.IsActive));
}
}
The TestConventionsAttribute is defined as:
internal class TestConventionsAttribute : AutoDataAttribute
{
internal TestConventionsAttribute()
: base(new Fixture().Customize(new TestConventions()))
{
}
private class TestConventions : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<MyClass>(c => c.With(x => x.IsActive, true));
}
}
}
Thank you, Nikos. This is very useful. Just a small update, now after a while and couple of versions after there is a small change with regards to the base constructor which should be called, the one above is now obsolete. It should look something like this:
private static readonly Func<IFixture> fixtureFactory = () =>
{
return new Fixture().Customize(new TestConventions());
};
public TestConventionsAttribute()
: base(fixtureFactory)
{
}
private class TestConventions : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customize<MyClass>(c => c.With(x => x.IsActive, true));
}
}
I have implemented UnitOfWork and GenericRepository following some tutorials.
I have IEFDbContext/EFDbContext class that takes care about Database, my IUnitofWork is as follows...
public interface IUnitOfWork : IDisposable
{
IGenericRepository<TEntity> GetRepository<TEntity>() where TEntity : class;
void Save();
}
And IGenericRepository as follows
public interface IGenericRepository<T> where T : class
{
IQueryable<T> Get();
T GetByID(object id);
void Add(T entity);
void Delete(T entity);
void DeleteAll(IEnumerable<T> entity);
void Update(T entity);
bool Any();
}
My controller is as follows...
public class ProjectController : Controller
{
private IGenericRepository<Project> ProjectRepo { get; set; }
private IUnitOfWork _unitOfWork { get; set; }
public ProjectController(IUnitOfWork uow)
{
_unitOfWork = uow;
ProjectRepo = _unitOfWork.GetRepository<Project>();
}
}
My create action is as follows
[HttpPost]
public ActionResult Create(AddProjectModel model)
{
if (ModelState.IsValid)
{
ProjectRepo.Add(newProject);
_unitOfWork.Save();
}
}
Everything works when I run the application, I am aware about why to use IuitofWork and GenericRepository, and that is why I am not creating IProjectRepository and then injecting that here...
My question is with unit testing this action.
I have created MockGenericRepository and MockUnitofWork in my Test project as follows...
public class MockUnitOfWork<TContext> : IUnitOfWork where TContext : class, new()
{
private TContext _ctx;
private Dictionary<Type, object> _repositories;
public MockUnitOfWork()
{
_ctx = new TContext();
_repositories = new Dictionary<Type, object>();
}
public IGenericRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
if (_repositories.Keys.Contains(typeof(TEntity)))
{
return _repositories[typeof(TEntity)] as IGenericRepository<TEntity>;
}
var entityName = typeof(TEntity).Name;
var prop = _ctx.GetType().GetProperty(entityName);
MockRepository<TEntity> repository = null;
if (prop != null)
{
var entityValue = prop.GetValue(_ctx, null);
repository = new MockRepository<TEntity>(entityValue as List<TEntity>);
}
else
{
repository = new MockRepository<TEntity>(new List<TEntity>());
}
_repositories.Add(typeof(TEntity), repository);
return repository;
}
public void SetRepositoryData<TEntity>(List<TEntity> data) where TEntity : class
{
IGenericRepository<TEntity> repo = GetRepository<TEntity>();
var mockRepo = repo as MockRepository<TEntity>;
if (mockRepo != null)
{
mockRepo._context = data;
}
}
public void Save()
{
}
public void Dispose()
{
}
}
And MockGenericRepository as follows
public class MockRepository<T> : IGenericRepository<T> where T : class
{
public List<T> _context;
public MockRepository(List<T> ctx)
{
_context = ctx;
}
public IQueryable<T> Get()
{
return _context.AsQueryable();
}
public T GetByID(object id)
{
// return _context.Find(s => s.Id == id).SingleOrDefault();
throw new NotImplementedException();
}
public virtual void Add(T entity)
{
_context.Add(entity);
}
public virtual void Delete(T entity)
{
_context.Remove(entity);
}
public virtual void DeleteAll(IEnumerable<T> entity)
{
_context.RemoveAll(s => s == entity);
}
public virtual void Update(T entity)
{
var entry = _context.Where(s => s == entity).SingleOrDefault();
entry = entity;
}
public virtual bool Any()
{
return _context.Any();
}
}
My ProjectControllerTest is as follows...
public class ProjectControllerTest
{
private readonly List<ALCProject> _projectsList;
private readonly IUnitOfWork _mockU = new MockUnitOfWork<EFDbContext>();
private ProjectController GetControllerObject()
{
foreach (var project in _projectsList)
{
_mockU.GetRepository<Project>().Add(project);
}
var controller = new ProjectController(_mockU);
return controller;
}
[Fact]
public void TestCreateProject()
{
var controller = GetControllerObject();
var result = controller.Create(new AddProjectModel());
Assert.Equal(_mockU.GetRepository<Project>().Get().Count(),4);
}
The issue I have is that my test does passes but when I look inside _mockU.GetRepository().Get() I can see that a new project is added but the "ID" field is 0, I understand the reason for this is because my MockGenericRepsoiotry has context define as public List _context; and that why its just adding new project in the list.
Can someone guide me how can I make it to generate new ID I think I have to Fake EFDbContext but I dont know how ???
The Project has an Id of 0 because nothing is setting it to anything else! It is most likely the Id property of the entity is mapped to an identity column in your database (SQL Server as a guess). When DbContext.Save() is called, it performs an insert operation in SQL. SQL Server is generating a new unique Id value for that row, returning this back to Entity Framework. EF then populates the value back into the object that it was persisting.
Your mock unit of work doesn't actually call DbContext.Save(), despite the fact that it is using the EF context as the data store for the repositories that it returns. You could enhance it by putting code in your MockUnitOfWork<T>.Save() method to provide a number to any Id property that has a value of zero in any of the repositories.
Or, as you say, this is a unit test so perhaps you shouldn't care.
I cannot quite see why your unit of work mock is looking at the Entity Framework context at all. Why not always return a repository based on a List<TEntity>?
I have a simple Http module:
public class CustomLoggingModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += BeginRequest;
context.EndRequest += EndRequest;
}
public void BeginRequest(object sender, EventArgs eventArgs)
{
//some code
}
public void EndRequest(object sender, EventArgs eventArgs)
{
//some
}
public void Dispose()
{
}
}
How can I unit test this? Especially how is it possible to mock events? Can anyone give some simple example?
Not sure why you have decided to hardwire the dependencies as new LogService() and new HttpContextWrapper(HttpContext.Current) within the CustomLoggingModule. If want to test whether LogInfo() method is called or not, it becomes lot easier if you can externalize these dependencies so you can inject stubbed/mocked version etc.
Also your question does not state that you are using an IOC container. You can register the HttpModule with the container and provide external dependencies at runtime. Your question also does not state that using an isoloation/mock object framework.
Therefore I will provide you with a solution that you can verify whether LogInfo method is called, using hand written stubs and mocks.
To achieve this, we need to refactor CustomLoggingModule a bit, so it becomes more testable.
System Under Test (SUT)
public class CustomLoggingModule : IHttpModule
{
public ILogService LogService { get; set; }
public Func<ILoggingHttpContextWrapper> LogginHttpContextWrapperDelegate { get; set; }
public void Init(HttpApplication context) {
context.BeginRequest += BeginRequest;
context.EndRequest += EndRequest;
}
public CustomLoggingModule() {
LogginHttpContextWrapperDelegate = () => new LoggingHttpContextWrapper();
}
public void BeginRequest(object sender, EventArgs eventArgs) {
LogService.LogInfo(LogginHttpContextWrapperDelegate().HttpContextWrapper);
}
public void EndRequest(object sender, EventArgs eventArgs) {
//some
}
public void Dispose(){ }
}
As you see above, I have introduced 2 additional properties - ILogService so I can provide a Mocked verion and a delegate Func which allows me to stub the
new HttpContextWrapper(HttpContext.Current);
public interface ILoggingHttpContextWrapper {
HttpContextWrapper HttpContextWrapper { get; }
}
public class LoggingHttpContextWrapper : ILoggingHttpContextWrapper
{
public LoggingHttpContextWrapper() {
HttpContextWrapper = new HttpContextWrapper(HttpContext.Current);
}
public HttpContextWrapper HttpContextWrapper { get; private set; }
}
And then your real ILogService
public interface ILogService {
void LogInfo(HttpContextWrapper httpContextWrapper);
}
public class LogService : ILogService {
public void LogInfo(HttpContextWrapper httpContextWrapper)
{
//real logger implementation
}
}
Unit Test :
You would create a MockLoggerService, so you can verify the interaction i,e whether the LogInfo() method was called, etc. You also need a stubbed LoggingHttpContextWrapper to provide the fake HttpContextWrapper to the SUT (System Under Test)/ CustomLoggingModule.
public class StubLoggingHttpContextWrapper : ILoggingHttpContextWrapper
{
public StubLoggingHttpContextWrapper(){}
public HttpContextWrapper HttpContextWrapper { get; private set; }
}
public class MockLoggerService : ILogService
{
public bool LogInfoMethodIsCalled = false;
public void LogInfo(HttpContextWrapper httpContextWrapper) {
LogInfoMethodIsCalled = true;
}
}
MockLoggerService is very important. It is not the real logger service, but it is the mocked version. When we do public class MockLoggerService : ILogService this means that we are providing another layer of indirection to the logger service so we can verify the interaction of the behaviour.
You also notice that I have provided a boolean variable to verify whether the LogInfo method is called or not. This allows me to call this method from the SUT, and verify whether the method being called or not.
Now Your Unit Test can be implemented as below.
[TestMethod]
public void CustomLoggingModule_BeginRequest_VerifyLogInfoMethodIsCalled()
{
var sut = new CustomLoggingModule();
var loggerServiceMock = new MockLoggerService();
var loggingHttpContextWrapperStub = new StubLoggingHttpContextWrapper();
sut.LogService = loggerServiceMock;
sut.LogginHttpContextWrapperDelegate = () => loggingHttpContextWrapperStub;
sut.BeginRequest(new object(), new EventArgs());
Assert.IsTrue(loggerServiceMock.LogInfoMethodIsCalled);
}
I had the same issue with my custom http module and decided I won't give up that easily and will do all I can to trigger the BeginRequest event in unit test. I had to actually read through the source code of HttpApplication class and use reflection to invoke the method.
[TestMethod]
public void EventTriggered_DoesNotError()
{
using (var application = new HttpApplication())
{
var module = new CustomLoggingModule();
module.Init(application);
FireHttpApplicationEvent(application, "EventBeginRequest", this, EventArgs.Empty);
}
}
private static void FireHttpApplicationEvent(object onMe, string invokeMe, params object[] args)
{
var objectType = onMe.GetType();
object eventIndex = (object)objectType.GetField(invokeMe, System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(onMe);
EventHandlerList events = (EventHandlerList)objectType.GetField("_events", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(onMe);
EventHandler handler = (EventHandler)events[eventIndex];
Delegate[] delegates = handler.GetInvocationList();
foreach (Delegate dlg in delegates)
{
dlg.Method.Invoke(dlg.Target, args);
}
}
Supposing that there are two repository interface :
interface IFooRepository
{
void Delete(int id);
}
interface IBarRepository
{
void Delete(int id);
}
And an IUnitOfWork interface like :
interface IUnitOfWork : IDisposable
{
void Commit();
void Rollback();
}
what is the best practices of implementing those interface using ServiceStack.ORMLite so that user can use them like
MyFooRepository.Delete(4);
// if an Exception throws here, Bar won't be deleted
MyBarRepository.Delete(7);
Or
using (var uow = CreateUnitOfWork())
{
MyFooRepository.Delete(4);
MyBarRepository.Delete(7);
uow.Commit(); //now they are in an transaction
}
Not sure of your need for Repository + UnitOfWork patterns but I think there are some alternative solutions in ServiceStack + OrmLite that keep your code 'DRY' before you need to introduce any patterns (especially if you're mainly seeking Transaction/Rollback support). Something like below is where I would start.
public class Foo //POCO for data access
{
//Add Attributes for Ormlite
public int Id { get; set; }
}
public class Bar //POCO for data access
{
//Add Attributes for Ormlite
public int Id { get; set; }
}
//your request class which is passed to your service
public class DeleteById
{
public int Id { get; set; }
}
public class FooBarService : MyServiceBase //MyServiceBase has resusable method for handling transactions.
{
public object Post(DeleteById request)
{
DbExec(dbConn =>
{
dbConn.DeleteById<Foo>(request.Id);
dbConn.DeleteById<Bar>(request.Id);
});
return null;
}
}
public class MyServiceBase : Service
{
public IDbConnectionFactory DbFactory { get; set; }
protected void DbExec(Action<IDbConnection> actions)
{
using (var dbConn = DbFactory.OpenDbConnection())
{
using (var trans = dbConn.OpenTransaction())
{
try
{
actions(dbConn);
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
throw ex;
}
}
}
}
}
Some references...
https://github.com/ServiceStack/ServiceStack.RedisWebServices - The above code is modified from this example
https://groups.google.com/forum/#!msg/servicestack/1pA41E33QII/R-trWwzYgjEJ - discussion about layers in ServiceStack
http://ayende.com/blog/3955/repository-is-the-new-singleton - Ayende Rahien (NHibernate core contributor) on Repository pattern