M
M
MADm2016-03-28 14:20:51
ASP.NET
MADm, 2016-03-28 14:20:51

How to write tests in asp.net mvc without affecting Entity Framework?

How to mock EF without using an unnecessary layer of abstraction with repositories so that all the functionality of EF remains working? Now in the test I use this approach:

var mockSet = new Mock<DbSet<tarif>>();
            var data = new List<tarif>
            {
                new tarif { id = 1, name = "Entity 1" },
                new tarif { id = 2, name = "Entity 2" }
            }.AsQueryable();

            mockSet.As<IQueryable<tarif>>().Setup(m => m.Provider).Returns(data.Provider);
            mockSet.As<IQueryable<tarif>>().Setup(m => m.Expression).Returns(data.Expression);
            mockSet.As<IQueryable<tarif>>().Setup(m => m.ElementType).Returns(data.ElementType);
            mockSet.As<IQueryable<tarif>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

            var customDbContextMock = new Mock<callerEntities>();
            customDbContextMock.Setup(x => x.tarifs).Returns(mockSet.Object);

but methods like .Remove() do not work
and how, for example, to test a piece of code in which EF works with a stored procedure?
Database.SqlQuery<GetSiteWidget_Result>("GetSiteWidgetAll").ToList()

Answer the question

In order to leave comments, you need to log in

3 answer(s)
M
MADm, 2016-03-29
@MADm

Added mocking remove, removerange, add, addrange and put it into a generic method

public static DbSet<T> MockDbSet<T>(List<T> table) where T : class
        {
            var dbSet = new Mock<DbSet<T>>();
            dbSet.As<IQueryable<T>>().Setup(q => q.Provider).Returns(() => table.AsQueryable().Provider);
            dbSet.As<IQueryable<T>>().Setup(q => q.Expression).Returns(() => table.AsQueryable().Expression);
            dbSet.As<IQueryable<T>>().Setup(q => q.ElementType).Returns(() => table.AsQueryable().ElementType);
            dbSet.As<IQueryable<T>>().Setup(q => q.GetEnumerator()).Returns(() => table.AsQueryable().GetEnumerator());
            dbSet.Setup(set => set.Add(It.IsAny<T>())).Callback<T>(table.Add);
            dbSet.Setup(set => set.AddRange(It.IsAny<IEnumerable<T>>())).Callback<IEnumerable<T>>(table.AddRange);
            dbSet.Setup(set => set.Remove(It.IsAny<T>())).Callback<T>(t => table.Remove(t));
            dbSet.Setup(set => set.RemoveRange(It.IsAny<IEnumerable<T>>())).Callback<IEnumerable<T>>(ts =>
            {
                foreach (var t in ts) { table.Remove(t); }
            });
            return dbSet.Object;
        }

Suitable for my needs so far.
Let me explain why I don't like the repositories approach. If you do not use the generic repository, then the code will grow n times for each table. Then it turns out that we need to make generic then inherit each entity from it and it turns out that we have a bunch of repositories. How will they be contacted then? we put them into one class and get the same dbcontext that generates ef and the repositories in it are the same dbset. That is, we create an abstraction over an abstraction so that we can inherit methods for tests from it. I don’t really see the point of this, apart from the obvious disadvantages of losing part of the context functionality.

S
Stanislav Makarov, 2016-03-28
@Nipheris

How to mock EF without using an unnecessary layer of abstraction with repositories so that all the functionality of EF remains working?

Maybe he's not like that, he's not needed? The repository is needed, among other things, in order to have a clear list of methods for testing. I can't really understand what you're testing right now.

M
Michael, 2016-03-28
@Sing303

Option 1:
Use unlimited frameworks, like Typemock, it will allow you to fake anything, private and static methods
Option 2:
Use a repository. The need to use Typemock indicates that the code "smells bad" and something is clearly wrong in it.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question