I'm going to test my EF Models. In order to do this I've create IDbContext class. But I don't know how to rewrite my Save and Delete methods, because I don't know how to write
db.Partner.AddObject(obj); How to rewrite these methods?
public interface IDbContext
{
int SaveChanges();
DbSet<Partner> Partner { get; set; }
}
public class PartnerRepository : IPartnerRepository
{
readonly IDbContext _context;
public PartnerRepository()
{
_context = (IDbContext)new VostokPortalEntities();
}
public PartnerRepository(IDbContext context)
{
_context = context;
}
public void Save(Partner obj)
{
using (var db = new VostokPortalEntities())
{
if (obj.PartnerID == 0)
{
db.Partner.AddObject(obj);
}
else
{
db.Partner.Attach(obj);
db.ObjectStateManager.ChangeObjectState(obj, System.Data.EntityState.Modified);
}
db.SaveChanges();
}
}
public void Delete(Partner obj)
{
using (var db = new VostokPortalEntities())
{
db.Partner.Attach(obj);
db.ObjectStateManager.ChangeObjectState(obj, System.Data.EntityState.Deleted);
db.SaveChanges();
}
}
public List<Partner> GetAll()
{
using (var db = new VostokPortalEntities())
{
return db.Partner.OrderByDescending(i => i.PartnerID).ToList();
}
}
}
Is this proper way to test EF Models?
Unit-testing of repositories takes a lot of time and does not give you many benefits. Why? Because repository don't have complex business logic. Usually there is pretty simple calls to underlying data-access API (i.e. ORM). I think it's match better to spend time on writing full-stack acceptance tests, which also will show if your repository do its job.
BTW there is interesting rule Don't Mock what you don't own:
By testing interactions with a mocked version of type we don't own, we
really are not using our test to check for the correct behavior, nor
to drive out a collaborator’s design. All our test is doing is
reiterating our guess as to how the other type works. Sure, it’s
better than no test, but not necessarily by much.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
If you don't care about the code I wrote and just want to have a discussion about abstracting existing abstractions... skip to the last 3 paragraphs.
I was introduced to the idea of Repositories and the Unit Of Work on top of Entity Framework via a Pluralsight lesson I was watching. I also stubmled upon Microsoft's own page detailing this process: http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
So I decided to try it out. I set out to write my own Unit Of Work class with generic Repositories on top of Entity Framework, making absolutely everything along the way utilize interfaces so I could inject my own mocks for testing.
First things first, for this exercise I chose to make a simple Blog application.
So I started with the DbContext. Gotta make sure I use an interface!
public interface ISimpleBlogContext : IDisposable
{
IDbSet<Blog> Blogs { get; }
IDbSet<Post> Posts { get; }
void SaveChanges();
IDbSet<T> Set<T>() where T : class;
DbEntityEntry Entry<T>(T entity) where T : class;
}
I'm sure everybody knows what the IDbSets are for, but the SaveChanges, Set, and Entry methods might look a bit out of place. Don't worry, we'll get to those later.
So now I hooked up my interface into an actual concrete DbContext :
public class SimpleBlogContext : DbContext, ISimpleBlogContext
{
public SimpleBlogContext() {
Database.SetInitializer<SimpleBlogContext>(new DropCreateDatabaseAlways<SimpleBlogContext>());
}
public IDbSet<Blog> Blogs { get; set; }
public IDbSet<Post> Posts { get; set; }
public DbEntityEntry Entry<T>(T entity) where T : class
{
return Entry<T>(entity);
}
void ISimpleBlogContext.SaveChanges()
{
SaveChanges();
}
IDbSet<T> ISimpleBlogContext.Set<T>()
{
return Set<T>();
}
The database initializer is just ensuring that for this test application the database is dropped and recreated each time I run the app. This was just an exercise and not a real app after all. You can see the SaveChanges, Set, and Entry methods implemented here, and they're all nothing more than wrappers for the DbContext methods of the same name.
So now on to the repositories...
I wasn't going to re-write virtually the same repository code for every entity I might add to my application (although in this case I'll only wind up using one repository), so I made a generic repository. Don't skip the interface!
public interface IGenericRepository<T>
where T : class
{
IEnumerable<T> GetAll();
T GetById(object id);
IEnumerable<T> GetByExpression(Expression<Func<T, bool>> expression);
void Add(T entity);
void Delete(T entity);
void Update(T entity);
}
and the concrete version... (notice I'm using my ISimpleBlogContext here instead of a concrete DbContext class because I want to be able to test all the things. Also, now you know why I had to write those Set, Entry, and SaveChanges methods in my ISimpleBlogContext interface)
public class GenericRepository<T> : IGenericRepository<T>
where T : class
{
public GenericRepository(ISimpleBlogContext context)
{
this.context = context;
}
private ISimpleBlogContext context;
public void Add(T entity)
{
context.Set<T>().Add(entity);
}
public void Delete(T entity)
{
context.Set<T>().Remove(entity);
}
public IEnumerable<T> GetAll()
{
return context.Set<T>().ToList<T>();
}
public IEnumerable<T> GetByExpression(Expression<Func<T, bool>> expression)
{
return context.Set<T>().Where<T>(expression).ToList<T>();
}
public T GetById(object id)
{
return context.Set<T>().Find(id);
}
public void Update(T entity)
{
context.Entry(entity).State = EntityState.Modified;
}
}
And now finally, the Unit Of Work class
public class UnitOfWork : IDisposable
{
public void Dispose()
{
if (context != null)
{
context.Dispose();
context = null;
}
}
public UnitOfWork()
{
context = new SimpleBlogContext();
}
public UnitOfWork(ISimpleBlogContext context)
{
this.context = context;
}
private ISimpleBlogContext context;
public GenericRepository<TEntity> GetRepository<TEntity>() where TEntity : class
{
return new GenericRepository<TEntity>(context);
}
public void Save()
{
context.SaveChanges();
}
}
I'm still allowing an ISimpleBlogContext to be passed in via the overloaded constructor, but the default constructor is where we finally get our concrete SimpleBlogContext DbContext from.
So now I just have to test all this. So I wrote a simple Console application which does nothing more than generate a couple of fake blogs with a couple of fake posts and save them using the Unit Of Work class. Then it loops the blogs and posts and prints them out so I can verify that they were actually saved to the database.
P.S. Jake is my dog in case you're wondering about the barking...
class Program
{
static void Main(string[] args)
{
UnitOfWork unitOfWork = new UnitOfWork();
GenericRepository<Blog> blogRepository = unitOfWork.GetRepository<Blog>();
Blog paulsBlog = new Blog()
{
Author = "Paul",
Posts = new List<Post>()
{
new Post()
{
Title = "My First Post",
Body = "This is my first post"
},
new Post()
{
Title = "My Second Post",
Body = "This is my second post"
}
}
};
Blog jakesBlog = new Blog()
{
Author = "Jake",
Posts = new List<Post>()
{
new Post()
{
Title = "Dog thoughts",
Body = "Bark bark bark"
},
new Post()
{
Title = "I like barking",
Body = "Bark bark bark"
}
}
};
blogRepository.Add(paulsBlog);
blogRepository.Add(jakesBlog);
unitOfWork.Save();
List<Blog> blogs = blogRepository.GetAll() as List<Blog>;
foreach (Blog blog in blogs)
{
System.Console.WriteLine("ID: {0}, Author: {1}\n", blog.Id, blog.Author);
if (blog.Posts != null && blog.Posts.Count > 0)
{
foreach (Post post in blog.Posts)
{
System.Console.WriteLine("Posted at: {0}, Title: {1}, Body: {2}", post.PostTime, post.Title, post.Body);
}
}
else
{
System.Console.WriteLine("No posts");
}
System.Console.WriteLine("\n");
}
}
}
It works. Yay!
My question, however, is simply... what did I gain exactly by doing any of this?
Isn't DbContext already a Unit Of Work and DbSet is already a repository? It seems all I did was write a really elaborate wrapper for both of those things with no added functionality at all. You might say that it's more test-friendly since everything is using interfaces, but with mocking frameworks like Moq it's already possible to mock a DbSets and DbContexts. My repositories are generic so there is literally zero functionality that is specific to business logic. The Unit Of Work class is just a wrapper for DbContext and the generic Repositories are just wrappers for DbSet.
Can somebody explain to me why anybody would do this? I watched a ~4 hour Pluralsight lesson on this, plus went through all the trouble of actually doing it myself, and I still don't get it.
I did the same thin recently and I believe you gain the flexibility of testing your code without requiring actual access to a SQL database.
I'm using EF for the first time, in a WPF application, using MVVM pattern. I read a lot of stuff but I couldn't end up with a solution. My problem is how to integrate EF in my app.
The most common way I found is build your own Repository + UnitOfWork. I don't like it. Basically because I already have DbContext and DbSet that can work as unit of work and repository, so why reinvent the wheel?
So I tried to use DbContext directly from view models like this
public class BookCollectionViewModel : ViewModelBase
{
public void LoadCollection()
{
Books.clear();
var books = new List<Book>();
using(var ctx = new DbContext())
{
books = ctx.DbSet<Book>().ToList();
}
books.Foreach(b => Books.Add(b));
}
ObservableCollection<Book> Books { get; } = new ObservableCollection<Book>();
}
But I don't like to use DbContext directly from view models, so I built a service layer
public class DbServices
{
public TReturn Execute<TEntity>(Func<IDbSet<TEntity>, TReturn> func)
{
TReturn retVal = default(TReturn);
using(var ctx = new DbContext())
{
retVal = func(ctx.DbSet<TEntity>());
}
return retVal;
}
}
public class BookCollectionViewModel : ViewModelBase
{
private DbServices mDbServices = new DbServices();
public void LoadCollection()
{
Books.clear();
var books = mDbServices.Execute<Book>((dbSet) => return dbSet.ToList());
books.Foreach(b => Books.Add(b))
}
ObservableCollection<Book> Books { get; } = new ObservableCollection<Book>();
}
But this way every action is atomic, so when I modify an entity I have to call SaveChanges() every time or loose changes, because DbContext is always disposed. So why not create a class-wide DbContext?
public class DbServices
{
private Lazy<> mContext;
public DbServices()
{
mContext = new Lazy<TContext>(() => {return new DbContext();});
}
public TContext Context { get { return context.Value; } }
public TReturn Execute<TEntity>(Func<IDbSet<TEntity>, TReturn> func)
{
return func(Context.DbSet<TEntity>());
}
}
Unfortunately, this way again doesn't work, because once a dbcontext is created, it is never disposed... So how about explicitly Open/Close the DbContext?
The question is: Where and how should I create/dispose the DbContext? The only thing I'm sure of is that I don't want to rebuild repository and unit of work, since they already exist as DbContext and DbSet...
I'm in the same position. I find that any persistent repository on the client side causes users not to see each others' changes.
Here's a good video explaining why EF is not the same as a repository
https://www.youtube.com/watch?v=rtXpYpZdOzM
Also I found an excellent end-to-end tutorial on WPF,MVVM & EF
http://www.software-architects.com/devblog/2010/09/10/MVVM-Tutorial-from-Start-to-Finish.
In this he exposes the data through a WCF data service and detaches them from the dbcontext straight away.
Hope it helps
I have a Data Layer that uses one Unit of work that is is basically a wrapper of the EnityFramework data context.
With all the async await stuff going around, I thought I'd start trying to use this data layer with some async calls. (I'm new to asynchronous programming in general)
I quickly ran into the problem of "there is already an open data reader associated with this command" errors.
Is there a good way to make my Unit of work thread-safe? Or should I just be creating another instance of it when i'm about to make some calls (in others words..be more careful).
Are there any good resources to check out for doing this?
My few google searches didn't amount to much, so I thought I'd bring this question to SO.
My Uow looks something like this.
public class MyUnitOfWork: IMyUnitOfWork, IDisposable
{
private MyDbContext DbContext { get; set; }
protected IRepositoryProvider RepositoryProvider;
public MyUnitOfWork(IRepositoryProvider repositoryProvider)
{
CreateDbContext();
repositoryProvider.DbContext = DbContext;
RepositoryProvider = repositoryProvider;
}
public MyUnitOfWork(IRepositoryProvider repositoryProvider, MyDbContext context)
{
DbContext = context;
repositoryProvider.DbContext = DbContext;
RepositoryProvider = repositoryProvider;
}
public void CreateDbContext()
{
DbContext = new MyDbContext();
//Serialization false if we enable proxied entities
DbContext.Configuration.ProxyCreationEnabled = false;
//avoid serilaization trouble
DbContext.Configuration.LazyLoadingEnabled = false;
}
public void Commit()
{
DbContext.SaveChanges();
}
public IRepository<Person> Persons {get { return repositoryProvider.GetRepo<Person>(); } }
public IRepository<SomeOtherEntityType> SomeOtherType {get { return repositoryProvider.GetRepo<SomeOtherEntityType>(); } }
// IDisposable
// ...
}
This article has general guidelines on how to operate with DbContext, regarding lifetime, multithreading, etc.
http://msdn.microsoft.com/en-us/data/jj729737.aspx
I'm using LINQ-to-SQL with ASP.NET MVC 4, and as of this moment I have a repository layer which contacts a real database. This is not very good when I want to unit test.
Also there should never be a logic in the repository layer, so this is why I want to mock the LINQ DataContext so I can create a service layer that talks either to the mock DataContext or to the real DataContext.
I see that my LINQ DataContext class inherits DataContext, but there is no interface, so I can't really mock that. I also see that DataContext uses Table<> class and there exists an interface ITable, so I probably could mock that. Also my LINQ DataContext is a partial class, so maybe I could manipulate that in some kind of way?
When I google this, all articles are from 2008 and are outdated.
Can anyone guide me in the right appropriate direction?
Here is an example of what I want to do. I will have seperate service class for each controller.
public class MyServiceClass
{
IDataContext _context;
// Constructors with dependency injection
public MyServiceClass()
{
_context = new MyRealDataContext();
}
public MyServiceClass(IDataContext ctx)
{
_context = ctx;
}
// Service functions
public IEnumerable<ModelClass> GetAll()
{
return _context.ModelClass;
}
public ModelClass GetOne(int id)
{
return _context.Where(s => s.ID == id).SingleOrDefault();
}
}
Although Linq-to-Sql is still supported in .NET 4+, it has been pushed back in favor of Entity Framework. That's probably why you're finding mostly older articles.
Anyway the best way to go is to write your own DataAccess layer-interface, used through your application. You then can have an implementation of that interface that uses your linq-to-sql for production and a mocked implementation for your unit tests.
Use dependency injection to instantiate the actual implementation class.
For creating a mock implementation you do it either manually (Creating a class in your test project that implements the IDataContext interface but returns hard-coded data) or use one of the mocking frameworks around there.
I have not used every one of them but moq was quite nice. Microsoft has now also their framework in Visual Studio 2012 called Fakes, worth looking at.
Example of using moq
var expectedResultList = new List<ModelClass>(){ ... };
var mockDataContext = new Mock<IDataContext>();
mock.Setup(c => c.GetAll()).Returns(expectedResultList);
MyServiceClass service = new MyServiceClass(mockDataContext.Object);
var list = service.GetAll();
Assert.AreEqual(expectedResultList, list);
In this code you set up your mock object so that it will return your expected list when the GetAll method is called.
This way you can easily test your business logic based on different returns from your data access.
Example of IDataContext
public interface IDataContext<T>
{
IEnumerable<T> GetAll();
T GetById(int id);
int Save(T model);
}
public class LinqToSqlDataContext<T> : IDataContext<T>
{
private DataContext context = new DataContext();
public IEnumerable<T> GetAll()
{
// query datacontext and return enumerable
}
public T GetById(int id)
{
// query datacontext and return object
}
public int Save(T model)
{
// save object in datacontext
}
}
public class MyFirstServiceClass
{
private IDataContext<MyClass> context;
public MyFirstServiceClass(IDataContext<MyClass> ctx)
{
this.context = ctx;
}
....
}
public class MySecondServiceClass
{
private IDataContext<MySecondClass> context;
public MyFirstServiceClass(IDataContext<MySecondClass> ctx)
{
this.context = ctx;
}
....
}
I am trying to figure out how to write Entity Framework Code First code via TDD. I am finding it hard since it I do not have a test database as I have had in the past with Ruby On Rails. Probably easier to explain with an example:
Currently I have:
public interface IMyContext
{
IDbSet<UserProfile> Users { get; set; }
}
and
public class UserModel
{
IMyContext myContext;
UserModel(IMyContext myContext)
{
this.myContext = myContext;
}
UserProfile GetUser(int id)
{
return myContext.Users.Where(u => u.id == id);
}
}
I am not sure how to test the UserModel code without a running database. I am aware that I can mock the MyContext - but the code myContext.Users.Where ... may involve complex mocking? Have I structured the code wrong? How can I write tests for models without having a test database? Or should I fake the context?
Thanks!
Break your code down into core components and you will realize that all you need to do is mock the context's Users property. After that, the Where is really just a static method working against an IEnumerable object
var users = myContext.Users;
var returnEnumerable = Enumerable.Where(users, u=>u.id == id);
return returnEnumerable
So, just mock your context in such a way that when .Users is called, it returns an IDbSet<UserProfile> of your making