JustMock - How to mock a method for all instances by returning the result of the equivalent method of another class (sharing a common interface - justmock

I am working with .NET 4.5, EF6 and I'm trying to use JustMock 2.0 to test my application.
I am trying to mock my database by mocking my DbContext subclass: CoreDataRepositoryContext.
To do it, I need to mock the member SaveChanges of DbContext and every DbSet typed properties of my class CoreDataRepositoryContext by returning a fake data collection. I also need to mock the following DbSet's members:
Add
Remove
AsQueryable
I need to mock it for all instances of CoreDataRepositoryContext and DbSet
For example, I have entities of type Order in database (table Orders)
I did the following to mock the table Orders:
// FakeOrders is a list of orders (List<Order>)
var mockedContext = Mock.Create<CoreDataRepositoryContext>();
// Mock works
Mock.Arrange(() => mockedContext.SaveChanges()).IgnoreInstance().DoNothing();
// Mock works
Mock.Arrange(() => mockedContext.Orders).IgnoreInstance().ReturnsCollection(FakeOrders);
// Mock works
Mock.Arrange(() => mockedContext.Orders.Add(Arg.IsAny<Order>())).IgnoreInstance().DoInstead((Order o) => FakeOrders.Add(o));
// Mock works
Mock.Arrange(() => mockedContext.Orders.Remove(Arg.IsAny<Order>())).IgnoreInstance().DoInstead((Order o) => FakeOrders.Remove(o));
// Mock DOES NOT work !
Mock.Arrange(() => mockedContext.Orders.AsQueryable()).IgnoreInstance().Returns(() => FakeOrders.AsQueryable());
mockedContext.Orders is of type DbSet< Order > and FakeOrders is of type List< Order >. Both classes implement the interface IEnumerable< Order >.
Mocking Add and Remove members work well because neither of the two methods is declared in the interface IEnumerable< T >.
On the other hand, AsQueryable is declared in this interface and defined by Queryable. So, as I mock the member using IgnoreInstance, calling AsQueryable from an instance of any class which implements IEnumerable< T > launches a never ending loop. Because IEnumerable< Order >.AsQueryable is mocked by FakeOrders.AsQueryable which is mocked by... FakeOrders.AsQueryable... infinite loop...
var query = mockedContext.Orders.AsQueryable(); // Infinite loop
query = FakeOrders.AsQueryable(); // Infinite loop
query = new List<Order>().AsQueryable(); // Infinite loop
How can I do to only mock DbSet< Order >.AsQueryable specifically, without mocking IEnumerable< Order >.AsQueryable using IgnoreInstance?
Thank you for your help :)

You can just remove IgnoreInstance() from the last arrangement. This will make it work only when called on that Orders property.
Although, technically, you don't need to arrange any of those methods on the Orders property. ReturnsCollection will take care to proxy all IList<T> and all IQueryable<T> methods to the target (if the target implements any of those interfaces). Since FakeOrders is a List, then Add and Remove on Orders will be proxied to the same methods on the backing collection. AsQueryable is not an instance method, but an extension method. As such, you can't mock it for a specific derived type, but you shouldn't even need to. The original implementation of AsQueryable is flexible enough, so you shouldn't need to mock it at all, ever.
If you simply remove the last three arrangements, your test will still work as expected.

Ok I have finally found a workaround:
I don't arrange DbContext with IgnoreInstance but I arrange the constructor of my DbContext subclass when called with a specific connection string as argument:
string myConnectionString = "CoreDBTestConnection";
// Arrange all CoreDataRepositoryContext instances for this connection string
Mock.Arrange(() => new CoreDataRepositoryContext(myConnectionString).Returns(GetMockContext());
The constructor is replaced by GetMockContext() which retruns a mocked context:
private static CoreDataRepositoryContext GetMockContext()
{
CoreDataRepositoryContext mockContext = new CoreDataRepositoryContext();
Mock.Arrange(() => mockContext.SaveChanges()).DoNothing();
Mock.Arrange(() => mockContext.Set<Order>()).ReturnsCollection(FakeOrders);
Mock.Arrange(() => mockContext.Orders).ReturnsCollection(FakeOrders);
Mock.Arrange(() => mockContext.Orders.Add(Arg.IsAny<Order>())).DoInstead((Order o) => FakeOrders.Add(o));
Mock.Arrange(() => mockContext.Orders.Remove(Arg.IsAny<Order>())).DoInstead((Order o) => FakeOrders.Remove(o));
Mock.Arrange(() => mockContext.Orders.Find(Arg.IsAny<object[]>())).Returns((object[] param) => FakeOrders.Find(x => x.Id == (Guid)param[0]));
Mock.Arrange(() => mockContext.Orders.AsQueryable()).Returns(() => FakeOrders.AsQueryable());
// Then arrange all DbSets...
return mockContext;
}
public static FakeDataList<Order> FakeOrders = new List<Order>();

Related

How to convert a method of a ValueObject to SQL with Entity Framework Core 3.1

I have this value object
public class ProductReference : ValueObject
{
protected ProductReference(){}
public ProductReference(string value){}
public string Value{get; protected set;}
}
I use it in my entity as :
public class Product : Entity<long>
{
protected Product(){}
public ProductReference Reference{get; protected set;}
}
In the OnModelCreating of my DbContext I defined :
modelBuilder.Entity<Product>(entity => {
entity.Property(a => a.Reference)
.HasColumnName("Reference")
.HasConversion(
a => a.Value,
s => new ProductReference (s);
});
When I do :
await dbcontext.Products.Where(p=>p.Reference.Value.Contains("some text")).toArrayAsync();
I get an exception
Expression cannot be converted to a valid SQL statement
I know for sure there is a way to create a custom expression converter, but I cannot find a good, simple and EF Core 3.1 compatible example to deal with my issue and that explain me clearly the concepts I miss.
I found this very interesting project
https://github.com/StevenRasmussen/EFCore.SqlServer.NodaTime
but it is too advanced for me to reproduce it for only my use case.
[EDIT] the ValueObject ans Entity are from
CSharpFunctionalExtensions nuget package, I dont think they are really relevant in my question.
I am not completely sure if i understand correctly what you want to accomplish, but you could try to configure your ProductReference as an Owned Entity Type.
Here you would transform the following code from:
modelBuilder.Entity<Product>(entity => {
entity.Property(a => a.Reference)
.HasColumnName("Reference")
.HasConversion(
a => a.Value,
s => new ProductReference (s);
});
to
modelBuilder.Entity<Product>(entity => {
entity.OwnsOne(a => a.Reference, referenceBuilder => {
referenceBuilder.Property(p => p.Value).HasColumnName("Reference");
});
});
With that your select statement should work.
It could be that you have to play around with the properties of your class ProductReference, or use some modifiers of the fluent API.
So first for some context on what is happening here behind the scenes and why its not gonna work even for build in simple converters like BoolToZeroOneConverter.
The problem here is that you are calling when converting the new ProductReference(s). This is method where you can do whatever you want in it. For example if use it in a Select statement it will again fail. For example:
await dbcontext.Products
.Select(x=>new ProductReference(x.Value))
.toArrayAsync();
The reason is obvious, it won't be able to translate. But why it cant transform it to a query?
Because you are passing a constructor. Inside this constructor you could be doing API calls or using Reflections to set the variables to your object, pretty much anything. That of course is not able to be translated in an SQL query.
Converters are generally used for in memory but they can be used for databse operations as well. This would mean that you will need something like this:
await dbcontext.Products
.Select(x=>new ProductReference() // empty constructor that does nothing
{
Property1 = x.Property1 // I don't know how the constructor maps them
})
.toArrayAsync();
Using this type of expression allow you to actually transalte the expression to an SQL statement and not making the conversion on the SQL DB and not in memory.
Now in your specific case using:
.HasConversion(
a => a.Value,
s => new ProductReference (){};
});
Should fix your issues but I fail to understand why would you want to initialize or convert a ProductReference to a ProductReference.

Can KeyFilter work through multiple levels?

I have a data access class that has its configuration data as a dependency. I then have a "data consumer" class that has the data access class as its dependency. I want to be able to select the configuration class in the constructor of the consumer.
I have this working in unit tests with the KeyFilter attribute. However, it only works through one layer - I have to eliminate the middle data access class layer. This doesn't work for my actual use case, but I believe it shows I'm using KeyFilter correctly.
Here is a test that passes:
[TestMethod]
public void ChooseCorrectlyThroughInterface()
{
var wrapper = new AutofacWrapper();
wrapper.Register<ITest, Test1>();
wrapper.Register<ITest, Test2>(UseTest2);
wrapper.Register<IConsumer1, Consumer1>();
wrapper.Register<IConsumer2, Consumer2>();
using (wrapper.BeginScope())
{
var c1 = wrapper.Get<IConsumer1>();
Assert.AreEqual("Test1", c1.ToString());
var c2 = wrapper.Get<IConsumer2>();
Assert.AreEqual("Test2", c2.ToString());
}
}
Consumer1's constructor looks like this:
public Consumer1(ITest test)
but Consumer2 uses a KeyFilter:
public Consumer2([KeyFilter(NamedBindingsShould.UseTest2)] ITest test)
My wrapper.Register method looks like this:
if (string.IsNullOrEmpty(name))
{
Builder.RegisterType<TImplementation>()
.As<TInterface>()
.WithAttributeFiltering();
}
else
{
Builder.RegisterType<TImplementation>()
.Named<TInterface>(name)
.WithAttributeFiltering();
}
This all works fine and the test passes. However, the real use case is to add a layer between where the KeyFilter is defined on the constructor and the dependency that needs to vary.
I want to specify two different database config classes:
wrapper.Register<IDatabaseConfigTest, DatabaseConfigDefault>();
wrapper.Register<IDatabaseConfigTest, DatabaseConfigAlternate>(Alternate);
but only one data access class:
wrapper.Register<IDatabaseTest, DatabaseTest>();
with this constructor:
public DatabaseTest(IDatabaseConfigTest config)
and specify the KeyFilter in the data consumer class constructor:
public DataConsumerDefault(IDatabaseTest database)
public DataConsumerAlternate([KeyFilter(NamedBindingsShould.Alternate)] IDatabaseTest database)
I had this working in Ninject with a lot of kung fu (no pun intended), but I'm trying to switch to Autofac and I can't seem to get it to work.
Is this possible in Autofac? Is there a different approach I can use besides KeyFilter? I have a sample test project I can attach or send if needed. I can also provide details as to how I did it in Ninject if that would help.
Soooo...thanks to https://autofaccn.readthedocs.io/en/latest/faq/select-by-context.html?highlight=AttributedMetadataModule%20#option-3-use-keyed-services
I changed my wrapper.Register method to this:
if (string.IsNullOrEmpty(name))
{
Builder.RegisterType<TImplementation>()
.As<TInterface>()
.WithAttributeFiltering();
}
else
{
Builder.RegisterType<TImplementation>()
.Named<TInterface>(name)
.WithParameter(
new ResolvedParameter(
(pi, ctx) => ctx.IsRegisteredWithName(name, pi.ParameterType),
(pi, ctx) => ctx.ResolveNamed(name, pi.ParameterType)))
.WithAttributeFiltering();
}
and it worked!
Thank you documentation.

How to mock the limitations of EntityFramework's implementation of IQueryable

I am currently writing unit tests for my repository implementation in an MVC4 application. In order to mock the data context, I started by adopting some ideas from this post, but I have now discovered some limitations that make me question whether it is even possible to properly mock IQueryable.
In particular, I have seen some situations where the tests pass but the code fails in production and I have not been able to find any way to mock the behavior that causes this failure.
For example, the following snippet is used to select Post entities that fall within a predefined list of categories:
var posts = repository.GetEntities<Post>(); // Returns IQueryable<Post>
var categories = GetCategoriesInGroup("Post"); // Returns a fixed list of type Category
var filtered = posts.Where(p => categories.Any(c => c.Name == p.Category)).ToList();
In my test environment, I have tried mocking posts using the fake DbSet implementation mentioned above, and also by creating a List of Post instances and converting it to IQueryable using the AsQueryable() extension method. Both of these approaches work under test conditions, but the code actually fails in production, with the following exception:
System.NotSupportedException : Unable to create a constant value of type 'Category'. Only primitive types or enumeration types are supported in this context.
Although LINQ issues like this are easy enough to fix, the real challenge is finding them, given that they do not reveal themselves in the test environment.
Am I being unrealistic in expecting that I can mock the behavior of Entity Framework's implementation of IQueryable?
Thanks for your ideas,
Tim.
I think it is very very hard, if impossible, to mock Entity Framework behaviour. First and foremost because it would require profound knowledge of all peculiarities and edge cases where linq-to-entites differs from linq-to-objects. As you say: the real challenge is finding them. Let me point out three main areas without claiming to be even nearly exhaustive:
Cases where Linq-to-Objects succeeds and Linq-to-Entities fails:
.Select(x => x.Property1.ToString(). LINQ to Entities does not recognize the method 'System.String ToString()' method... This applies to nearly all methods in native .Net classes and of course to own methods. Only a few .Net methods will be translated into SQL. See CLR Method to Canonical Function Mapping. As of EF 6.1, ToString is supported by the way. But only the parameterless overload.
Skip() without preceding OrderBy.
Except and Intersect: can produce monstrous queries that throw Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries.
Select(x => x.Date1 - x.Date2): DbArithmeticExpression arguments must have a numeric common type.
(your case) .Where(p => p.Category == category): Only primitive types or enumeration types are supported in this context.
Nodes.Where(n => n.ParentNodes.First().Id == 1): The method 'First' can only be used as a final query operation.
context.Nodes.Last(): LINQ to Entities does not recognize the method '...Last...'. This applies to many other IQueryable extension methods. See Supported and Unsupported LINQ Methods.
(See Slauma's comment below): .Select(x => new A { Property1 = (x.BoolProperty ? new B { BProp1 = x.Prop1, BProp2 = x.Prop2 } : new B { BProp1 = x.Prop1 }) }): The type 'B' appears in two structurally incompatible initializations within a single LINQ to Entities query... from here.
context.Entities.Cast<IEntity>(): Unable to cast the type 'Entity' to type 'IEntity'. LINQ to Entities only supports casting EDM primitive or enumeration types.
.Select(p => p.Category?.Name). Using null propagation in an expression throws CS8072 An expression tree lambda may not contain a null propagating operator. This may get fixed one day.
This question: Why does this combination of Select, Where and GroupBy cause an exception? made me aware of the fact that there are even entire query constructions that are not supported by EF, while L2O wouldn't have any trouble with them.
Cases where Linq-to-Objects fails and Linq-to-Entities succeeds:
.Select(p => p.Category.Name): when p.Category is null L2E returns null, but L2O throws Object reference not set to an instance of an object. This can't be fixed by using null propagation (see above).
Nodes.Max(n => n.ParentId.Value) with some null values for n.ParentId. L2E returns a max value, L2O throws Nullable object must have a value.
Using EntityFunctions (DbFunctions as of EF 6) or SqlFunctions.
Cases where both succeed/fail but behave differently:
Nodes.Include("ParentNodes"): L2O has no implementation of include. It will run and return nodes (if Nodes is IQueryable), but without parent nodes.
Nodes.Select(n => n.ParentNodes.Max(p => p.Id)) with some empty ParentNodes collections: both fail but with different exceptions.
Nodes.Where(n => n.Name.Contains("par")): L2O is case sensitive, L2E depends on the database collation (often not case sensitive).
node.ParentNode = parentNode: with a bidirectional relationship, in L2E this will also add the node to the nodes collection of the parent (relationship fixup). Not in L2O. (See Unit testing a two way EF relationship).
Work-around for failing null propagation: .Select(p => p.Category == null ? string.Empty : p.Category.Name): the result is the same, but the generated SQL query also contains the null check and may be harder to optimize.
Nodes.AsNoTracking().Select(n => n.ParentNode. This one is very tricky!. With AsNoTracking EF creates new ParentNode objects for each Node, so there can be duplicates. Without AsNoTracking EF reuses existing ParentNodes, because now the entity state manager and entity keys are involved. AsNoTracking() can be called in L2O, but it doesn't do anything, so there will never be a difference with or without it.
And what about mocking lazy/eager loading and the effect of context life cycle on lazy loading exceptions? Or the effect of some query constructs on performance (like constructs that trigger N+1 SQL queries). Or exceptions due to duplicate or missing entity keys? Or relationship fixup?
My opinion: nobody is going to fake that. The most alarming area is where L2O succeeds and L2E fails. Now what's the value of green unit tests? It has been said before that EF can only reliably be tested in integration tests (e.g. here) and I tend to agree.
However, that does not mean that we should forget about unit tests in projects with EF as data layer. There are ways to do it, but, I think, not without integration tests.
I have written a few Unit Tests with Entity Framework 6.1.3 using Moq and used it to override IQueryable. Note that all DbSet that should be tested needs to be marked as virtual. Example from Microsoft themselves:
Query:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
namespace TestingDemo
{
[TestClass]
public class QueryTests
{
[TestMethod]
public void GetAllBlogs_orders_by_name()
{
var data = new List<Blog>
{
new Blog { Name = "BBB" },
new Blog { Name = "ZZZ" },
new Blog { Name = "AAA" },
}.AsQueryable();
var mockSet = new Mock<DbSet<Blog>>();
mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(0 => data.GetEnumerator());
var mockContext = new Mock<BloggingContext>();
mockContext.Setup(c => c.Blogs).Returns(mockSet.Object);
var service = new BlogService(mockContext.Object);
var blogs = service.GetAllBlogs();
Assert.AreEqual(3, blogs.Count);
Assert.AreEqual("AAA", blogs[0].Name);
Assert.AreEqual("BBB", blogs[1].Name);
Assert.AreEqual("ZZZ", blogs[2].Name);
}
}
}
Insert:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Data.Entity;
namespace TestingDemo
{
[TestClass]
public class NonQueryTests
{
[TestMethod]
public void CreateBlog_saves_a_blog_via_context()
{
var mockSet = new Mock<DbSet<Blog>>();
var mockContext = new Mock<BloggingContext>();
mockContext.Setup(m => m.Blogs).Returns(mockSet.Object);
var service = new BlogService(mockContext.Object);
service.AddBlog("ADO.NET Blog", "http://blogs.msdn.com/adonet");
mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once());
mockContext.Verify(m => m.SaveChanges(), Times.Once());
}
}
}
Example service:
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
namespace TestingDemo
{
public class BlogService
{
private BloggingContext _context;
public BlogService(BloggingContext context)
{
_context = context;
}
public Blog AddBlog(string name, string url)
{
var blog = _context.Blogs.Add(new Blog { Name = name, Url = url });
_context.SaveChanges();
return blog;
}
public List<Blog> GetAllBlogs()
{
var query = from b in _context.Blogs
orderby b.Name
select b;
return query.ToList();
}
public async Task<List<Blog>> GetAllBlogsAsync()
{
var query = from b in _context.Blogs
orderby b.Name
select b;
return await query.ToListAsync();
}
}
}
Source: https://learn.microsoft.com/en-us/ef/ef6/fundamentals/testing/mocking

Decouple EF queries from BL - Extension Methods VS Class-Per-Query

I have read dozens of posts about PROs and CONs of trying to mock \ fake EF in the business logic.
I have not yet decided what to do - but one thing I know is - I have to separate the queries from the business logic.
In this post I saw that Ladislav has answered that there are 2 good ways:
Let them be where they are and use custom extension methods, query views, mapped database views or custom defining queries to define reusable parts.
Expose every single query as method on some separate class. The method
mustn't expose IQueryable and mustn't accept Expression as parameter =
whole query logic must be wrapped in the method. But this will make
your class covering related methods much like repository (the only one
which can be mocked or faked). This implementation is close to
implementation used with stored procedures.
Which method do you think is better any why ?
Are there ANY downsides to put the queries in their own place ? (maybe losing some functionality from EF or something like that)
Do I have to encapsulate even the simplest queries like:
using (MyDbContext entities = new MyDbContext)
{
User user = entities.Users.Find(userId); // ENCAPSULATE THIS ?
// Some BL Code here
}
So I guess your main point is testability of your code, isn't it? In such case you should start by counting responsibilities of the method you want to test and than refactor your code using single responsibility pattern.
Your example code has at least three responsibilities:
Creating an object is a responsibility - context is an object. Moreover it is and object you don't want to use in your unit test so you must move its creation elsewhere.
Executing query is a responsibility. Moreover it is a responsibility you would like to avoid in your unit test.
Doing some business logic is a responsibility
To simplify testing you should refactor your code and divide those responsibilities to separate methods.
public class MyBLClass()
{
public void MyBLMethod(int userId)
{
using (IMyContext entities = GetContext())
{
User user = GetUserFromDb(entities, userId);
// Some BL Code here
}
}
protected virtual IMyContext GetContext()
{
return new MyDbContext();
}
protected virtual User GetUserFromDb(IMyDbContext entities, int userId)
{
return entities.Users.Find(userId);
}
}
Now unit testing business logic should be piece of cake because your unit test can inherit your class and fake context factory method and query execution method and become fully independent on EF.
// NUnit unit test
[TestFixture]
public class MyBLClassTest : MyBLClass
{
private class FakeContext : IMyContext
{
// Create just empty implementation of context interface
}
private User _testUser;
[Test]
public void MyBLMethod_DoSomething()
{
// Test setup
int id = 10;
_testUser = new User
{
Id = id,
// rest is your expected test data - that is what faking is about
// faked method returns simply data your test method expects
};
// Execution of method under test
MyBLMethod(id);
// Test validation
// Assert something you expect to happen on _testUser instance
// inside MyBLMethod
}
protected override IMyContext GetContext()
{
return new FakeContext();
}
protected override User GetUserFromDb(IMyContext context, int userId)
{
return _testUser.Id == userId ? _testUser : null;
}
}
As you add more methods and your application grows you will refactor those query execution methods and context factory method to separate classes to follow single responsibility on classes as well - you will get context factory and either some query provider or in some cases repository (but that repository will never return IQueryable or get Expression as parameter in any of its methods). This will also allow you following DRY principle where your context creation and most commonly used queries will be defined only once on one central place.
So at the end you can have something like this:
public class MyBLClass()
{
private IContextFactory _contextFactory;
private IUserQueryProvider _userProvider;
public MyBLClass(IContextFactory contextFactory, IUserQueryProvider userProvider)
{
_contextFactory = contextFactory;
_userProvider = userProvider;
}
public void MyBLMethod(int userId)
{
using (IMyContext entities = _contextFactory.GetContext())
{
User user = _userProvider.GetSingle(entities, userId);
// Some BL Code here
}
}
}
Where those interfaces will look like:
public interface IContextFactory
{
IMyContext GetContext();
}
public class MyContextFactory : IContextFactory
{
public IMyContext GetContext()
{
// Here belongs any logic necessary to create context
// If you for example want to cache context per HTTP request
// you can implement logic here.
return new MyDbContext();
}
}
and
public interface IUserQueryProvider
{
User GetUser(int userId);
// Any other reusable queries for user entities
// Non of queries returns IQueryable or accepts Expression as parameter
// For example: IEnumerable<User> GetActiveUsers();
}
public class MyUserQueryProvider : IUserQueryProvider
{
public User GetUser(IMyContext context, int userId)
{
return context.Users.Find(userId);
}
// Implementation of other queries
// Only inside query implementations you can use extension methods on IQueryable
}
Your test will now only use fakes for context factory and query provider.
// NUnit + Moq unit test
[TestFixture]
public class MyBLClassTest
{
private class FakeContext : IMyContext
{
// Create just empty implementation of context interface
}
[Test]
public void MyBLMethod_DoSomething()
{
// Test setup
int id = 10;
var user = new User
{
Id = id,
// rest is your expected test data - that is what faking is about
// faked method returns simply data your test method expects
};
var contextFactory = new Mock<IContextFactory>();
contextFactory.Setup(f => f.GetContext()).Returns(new FakeContext());
var queryProvider = new Mock<IUserQueryProvider>();
queryProvider.Setup(f => f.GetUser(It.IsAny<IContextFactory>(), id)).Returns(user);
// Execution of method under test
var myBLClass = new MyBLClass(contextFactory.Object, queryProvider.Object);
myBLClass.MyBLMethod(id);
// Test validation
// Assert something you expect to happen on user instance
// inside MyBLMethod
}
}
It would be little bit different in case of repository which should have reference to context passed to its constructor prior to injecting it to your business class.
Your business class can still define some queries which are never use in any other classes - those queries are most probably part of its logic. You can also use extension methods to define some reusable part of queries but you must always use those extension methods outside of your core business logic which you want to unit test (either in query execution methods or in query provider / repository). That will allow you easy faking query provider or query execution methods.
I saw your previous question and thought about writing a blog post about that topic but the core of my opinion about testing with EF is in this answer.
Edit:
Repository is different topic which doesn't relate to your original question. Specific repository is still valid pattern. We are not against repositories, we are against generic repositories because they don't provide any additional features and don't solve any problem.
The problem is that repository alone doesn't solve anything. There are three patterns which have to be used together to form proper abstraction: Repository, Unit of Work and Specifications. All three are already available in EF: DbSet / ObjectSet as repositories, DbContext / ObjectContext as Unit of works and Linq to Entities as specifications. The main problem with custom implementation of generic repositories mentioned everywhere is that they replace only repository and unit of work with custom implementation but still depend on original specifications => abstraction is incomplete and it is leaking in tests where faked repository behaves in the same way as faked set / context.
The main disadvantage of my query provider is explicit method for any query you will need to execute. In case of repository you will not have such methods you will have just few methods accepting specification (but again those specifications should be defined in DRY principle) which will build query filtering conditions, ordering etc.
public interface IUserRepository
{
User Find(int userId);
IEnumerable<User> FindAll(ISpecification spec);
}
The discussion of this topic is far beyond the scope of this question and it requires you to do some self study.
Btw. mocking and faking has different purpose - you fake a call if you need to get testing data from method in the dependency and you mock the call if you need to assert that method on dependency was called with expected arguments.

Limiting EF result set permanently by overriding ObjectQuery ESQL

Does anyone have any idea how to limit result set of EntityFramework permanently? I'm speaking about something like this Conditional Mapping. This is exactly what I want to achieve with one exception: I want to do this programmatically. That's because condition value will be passed to EF only on context creation. Beside I don't want this column to disappear from mapping.
I know how to achieve this with EF2.0 and reflection. I was using CreateQuery() method to generate my own ObjectQuery. CreateQuery() allows to inject my own ESQL query with additional condition e.g. WHERE TABLE.ClientID == value.
Problem with EF40 is that there is no more ObjectQuery but only ObjectSet and CreateQuery() is not used. I have no idea how to inject my own ESQL query.
The reason why I want to limit result sets is that I want to separate clients data from each other. This separation should be done automatically inside context so that programmers will not have to add condition .Where(x => x.ClientID == 5) to each individual query.
Maybe my approach is completely bad — but I don't know any alternative.
You don't need reflection for this. You can simply use class inherited from ObjectContext or create custom implementation of UnitOfWork and Repositories which will wrap this functionality in better way (upper layer has access only to UnitOfWork and Repositories which do not expose EF context).
Simple example of object context:
public class CustomContext : ObjectContext
{
private ObjectSet<MyObject> _myObjectsSet;
private int _clientId;
public CustomContext(string connectionString, int clientId)
: base(connectionString)
{
_myObjectSet = CreateObjectSet<MyObject>();
_clientId = clientId;
}
public IQueryable<MyObject> MyObjectQuery
{
get
{
return _myObjectsSet.Where(o => o.ClientId == _clientId);
}
}
}