Getting my head all banged up trying to moq the interface below. The GetOrSet has me tripped up. The service comes from here
public interface ICacheService
{
T GetOrSet<T>(string cackeKey, int expiryInMinutes, Func<T> getItemCallback) where T : class;
}
public class CacheService : ICacheService
{
public T GetOrSet<T>(string cacheKey, int expiryInMinutes, Func<T> getItemCallback) where T : class
{
T item = MemoryCache.Default.Get(cacheKey) as T;
if (item == null)
{
item = getItemCallback();
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(expiryInMinutes));
}
return item;
}
}
Example in code:
var result = _cacheService.GetOrSet(
cacheKey,
cacheExpiry,
() => this.GetRoutes(routeType));
return result.Select(x => new Route(x));
Basic setup could look like:
public static ICacheService GetMockCacheService<T>() where T : class
{
var mock = new Mock<ICacheService>();
mock.Setup(service => service.GetOrSet(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<Func<T>>()))
.Returns(default(T));
return mock.Object;
}
Use a generic method to build your mock for whatever type you need in the implementation.
Related
I am making generic validators for checking input:
Interface:
public interface IInputValidator
{
bool CanHandle<T>();
bool Validate<T>(string? input, out T result);
}
Implementation:
public class IntegerValidator : IInputValidator
{
public bool CanHandle<T>()
{
return typeof(T) == typeof(int);
}
public bool Validate<T>(string? input, out T result)
{
var isValid = int.TryParse(input, out var res);
result = (T)(object)res;
return isValid;
}
}
Then I grab all the validators I have and inject like so: (it feels convenient that the interface itself is not generic thus I don't have to inject them one by one and able to group them in a single collection)
private readonly IEnumerable<IInputValidator> _inputValidators;
public CallerClass(IEnumerable<IInputValidator> inputValidators)
{
_inputValidators = inputValidators;
}
And call it like:
var validator = _inputValidators.First(r => r.CanHandle<int>());
var isInputValid = validator.Validate(userInput, out int id);
It all looks fine except for this line in implementation
result = (T)(object)res;
I feel like something is wrong here but can't figure out how to make it better. It works like this though.
The core issue is that you are trying to combine the resolution of the appropriate validator and the action of that validator into the same generic interface.
If you are willing to separate the resolver and validator functionality into two interfaces:
public interface IInputValidatorResolver
{
bool CanHandle<T>();
IInputValidator<T> GetValidator<T>();
}
public interface IInputValidator<T>
{
bool Validate(string? input, out T result);
}
you can work with IInputValidatorResolver instances in your CallerClass contract to instead resolve the appropriate validator and strongly-type you call to the validator without an object cast. The resolver implementations can create a cache that casts your Validator to a generic IInputValidator<T> instance.
public class IntegerValidatorResolver : IInputValidatorResolver
{
public bool CanHandle<T>() => typeof(T) == typeof(int);
public IInputValidator<T> GetValidator<T>() => Cache<T>.Validator;
private static class Cache<T>
{
public static readonly IInputValidator<T> Validator = BuildValidator();
private static IInputValidator<T> BuildValidator() => ((IInputValidator<T>)new IntegerValidator());
}
}
public class LongValidatorResolver : IInputValidatorResolver
{
public bool CanHandle<T>() => typeof(T) == typeof(long);
public IInputValidator<T> GetValidator<T>() => Cache<T>.Validator;
private static class Cache<T>
{
public static readonly IInputValidator<T> Validator = BuildValidator();
private static IInputValidator<T> BuildValidator() => ((IInputValidator<T>)new LongValidator());
}
}
public class IntegerValidator : IInputValidator<int>
{
public bool Validate(string? input, out int result) => int.TryParse(input, out result);
}
public class LongValidator : IInputValidator<long>
{
public bool Validate(string? input, out long result) => long.TryParse(input, out result);
}
and you can test it with the following:
IEnumerable<IInputValidatorResolver> validatorResolvers = new List<IInputValidatorResolver> { new IntegerValidatorResolver(), new LongValidatorResolver() };
var intValidator = validatorResolvers.First(x => x.CanHandle<int>()).GetValidator<int>();
var isIntValid = intValidator.Validate(long.MaxValue.ToString(), out int intResult);
Console.WriteLine(isIntValid);
Console.WriteLine(intResult);
var longValidator = validatorResolvers.First(x => x.CanHandle<long>()).GetValidator<long>();
var isLongValid = longValidator.Validate(long.MaxValue.ToString(), out long longResult);
Console.WriteLine(isLongValid);
Console.WriteLine(longResult);
That said, this creates an awkward contract where if you do NOT perform a check with CanHandle<T> first, your call to GetValidator<T> can throw an exception. In addition, in either this implementation or your current implementation, you have to loop through resolvers/validators to find the appropriate instance, which is unnecessarily wasteful.
As a result, it may make more sense to have a single IInputValidatorResolver instance that knows how to resolve the appropriate validator based on the type of T, without a CanHandle<T>() check.
public interface IInputValidatorResolver
{
IInputValidator<T> GetValidator<T>();
}
public class ValidatorResolver : IInputValidatorResolver
{
public IInputValidator<T> GetValidator<T>() => Cache<T>.Validator;
private static class Cache<T>
{
public static readonly IInputValidator<T> Validator = BuildValidator();
private static IInputValidator<T> BuildValidator()
{
if (typeof(T) == typeof(int))
{
return ((IInputValidator<T>)new IntegerValidator());
}
else if (typeof(T) == typeof(long))
{
return ((IInputValidator<T>)new LongValidator());
}
else
{
throw new ArgumentException($"{typeof(T).FullName} does not have a registered validator.");
}
}
}
}
public interface IInputValidator<T>
{
bool Validate(string? input, out T result);
}
public class IntegerValidator : IInputValidator<int>
{
public bool Validate(string? input, out int result) => int.TryParse(input, out result);
}
public class LongValidator : IInputValidator<long>
{
public bool Validate(string? input, out long result) => long.TryParse(input, out result);
}
This allows for a much cleaner API and far less registration and enumeration:
IInputValidatorResolver resolver = new ValidatorResolver();
var intValidator = resolver.GetValidator<int>();
var isIntValid = intValidator.Validate(long.MaxValue.ToString(), out int intResult);
Console.WriteLine(isIntValid);
Console.WriteLine(intResult);
var longValidator = resolver.GetValidator<long>();
var isLongValid = longValidator.Validate(long.MaxValue.ToString(), out long longResult);
Console.WriteLine(isLongValid);
Console.WriteLine(longResult);
UPDATE
It looks like you want a purely constructor-injection driven solution. You can accomplish this by registering a new interface as IEnumerable<IInputValidator> and injecting it into the resolver instance.
The IInputValidator interface is responsible for the CanHandle<T>() method that is checked prior to casting to IInputValidator<T>.
public interface IInputValidatorResolver
{
IInputValidator<T> GetValidator<T>();
}
public class ValidatorResolver : IInputValidatorResolver
{
private IEnumerable<IInputValidator?> _validators;
public ValidatorResolver(IEnumerable<IInputValidator?> validators)
{
_validators = validators;
}
public IInputValidator<T> GetValidator<T>()
{
foreach (var validator in _validators)
{
if (validator!.CanHandle<T>())
{
return (IInputValidator<T>)validator;
}
}
throw new ArgumentException($"{typeof(T).FullName} does not have a registered validator.");
}
}
public interface IInputValidator
{
bool CanHandle<TInput>();
}
public interface IInputValidator<T> : IInputValidator
{
bool Validate(string? input, out T result);
}
public class IntegerValidator : IInputValidator<int>
{
public bool CanHandle<T>() => typeof(T) == typeof(int);
public bool Validate(string? input, out int result) => int.TryParse(input, out result);
}
public class LongValidator : IInputValidator<long>
{
public bool CanHandle<T>() => typeof(T) == typeof(long);
public bool Validate(string? input, out long result) => long.TryParse(input, out result);
}
You can test this behavior with the following:
var servicesCollection = new ServiceCollection();
servicesCollection.AddTransient(typeof(IEnumerable<IInputValidator>), s =>
{
return new List<IInputValidator>
{
new IntegerValidator(),
new LongValidator()
};
});
servicesCollection.AddTransient<IInputValidatorResolver, ValidatorResolver>();
var serviceProvider = servicesCollection.BuildServiceProvider();
var resolver = serviceProvider.GetService<IInputValidatorResolver>();
var intValidator = resolver.GetValidator<int>();
var isIntValid = intValidator.Validate(long.MaxValue.ToString(), out int intResult);
Console.WriteLine(isIntValid);
Console.WriteLine(intResult);
var longValidator = resolver.GetValidator<long>();
var isLongValid = longValidator.Validate(long.MaxValue.ToString(), out long longResult);
Console.WriteLine(isLongValid);
Console.WriteLine(longResult);
With this approach, you no longer need the ValidationResolver. It is simply a way to encapsulate the logic of GetValidator<T>. You could just as easily inject IEnumerable<IInputValidator> into your consuming classes and perform the cast each time you need to use it.
Another option is to use Autofac's IComponentContext:
using Autofac;
using TransactionStorage.Interface;
namespace TransactionStorage.Core
{
public class InputResolver : IInputResolver
{
private readonly IComponentContext _context;
public InputResolver (IComponentContext context)
{
_context = context;
}
public bool Validate<T>(string? userInput, out T result) where T : struct
{
var validator = _context.Resolve<IInputValidator<T>>();
return validator.Validate(userInput, out result);
}
}
}
How to set up where linq extension on object? DbSet in my case. Here is my code:
this.workflowStateSet
.Setup(m => m.Where(It.IsAny<Expression<Func<Model.WorkflowState, int, bool>>>()))
.Returns(new List<Model.WorkflowState>().AsQueryable());
However, it gives me exception not very familiar exception:
System.NotSupportedException: Expression references a method that
does not belong to the mocked object: m => m.Where<WorkflowState>
I will be grateful for any hint.
This extension method will help mock the DbSet
public static class MockDbSetExtensions {
public static Mock<DbSet<T>> AsDbSetMock<T>(this IEnumerable<T> list) where T : class {
IQueryable<T> queryableList = list.AsQueryable();
Mock<DbSet<T>> dbSetMock = new Mock<DbSet<T>>();
dbSetMock.As<IQueryable<T>>().Setup(x => x.Provider).Returns(queryableList.Provider);
dbSetMock.As<IQueryable<T>>().Setup(x => x.Expression).Returns(queryableList.Expression);
dbSetMock.As<IQueryable<T>>().Setup(x => x.ElementType).Returns(queryableList.ElementType);
dbSetMock.As<IQueryable<T>>().Setup(x => x.GetEnumerator()).Returns(() => queryableList.GetEnumerator());
return dbSetMock;
}
}
And you can use it like this.
//Arrange
var data = new List<Model.WorkflowState>();
//you would populate your list as needed.
//convert it to a mock DbSet that uses the list as its datasource
var workflowStateSet = data.AsDbSetMock();
var dbSet = workflowStateSet.Object;
//Act
var items = dbSet.Where("Your expression here");
//Assert
//....
Use the repository pattern to add a layer of abstraction to the data retrieval. This abstraction can then be mocked.
If, for example, you were trying to retrieve all of the workflows with a stateId equal to 1, then rather than calling something like this
var result = DbSet.WorkflowState.Where(w => w.stateId == 1);
move this code into another class and then create an interface of the method signature.
public interface IWorkflowStateSetRepository{
IQueryable<Model.WorkflowState> GetAllWorkflows(int state);
}
implementation
public class WorkflowStateSetRepository : IWorkflowStateSetRepository{
public IQueryable<Model.WorkflowState> GetAllWorkflows(int state){
return DbSet.WorkflowState .Where(w => w.stateId == state);
}
}
In the calling code get an instance of IWorkflowStateSetRepository (probably from your IoC container) and call the GetAllWorkflows() method instead. This will give you the same results as before but you can now mock the interface in your tests and setup calls to that methods.
this.MockedIWorkflowStateSetRepository.Setup(m => m.GetAllWorkflows(It.IsAny<int>()))
.Returns(new List<Model.WorkflowState>().AsQueryable());
This code is more maintainable and (with appropriately named variables and methods) also conveys the intent a lot better.
The repository pattern is discussed in greater detail here;
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
Are you trying to Mock up a real DbSet instance ? Cause this won't work, as the error message try to explain you. To mock a type, it must either be an interface or have virtual members (abstract members are also virtual).
You can try to mock up IDbSet or to create a custom DbSet class, for instance something like the following class
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
public class DbSetMock<T> : DbSet<T>, IDbSet<T>
where T : class
{
private readonly ICollection<T> _contentCollection;
public DbSetMock(IList<T> contentCollection = null)
{
_contentCollection = new Collection<T>(contentCollection ?? new List<T>());
AddedEntities = new List<T>();
RemovedEntities = new List<T>();
AttachedEntities = new List<T>();
}
public void OverrideContentCollection(IEnumerable<T> newData)
{
_contentCollection.Clear();
_contentCollection.AddRange(newData);
}
public IList<T> AddedEntities { get; private set; }
public IList<T> AttachedEntities { get; private set; }
public override ObservableCollection<T> Local
{
get
{
throw new NotImplementedException();
}
}
public IList<T> RemovedEntities { get; private set; }
public Type ElementType
{
get
{
return typeof(T);
}
}
public Expression Expression
{
get
{
return _contentCollection.AsQueryable().Expression;
}
}
public IQueryProvider Provider
{
get
{
return _contentCollection.AsQueryable().Provider;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<T> GetEnumerator()
{
return _contentCollection.GetEnumerator();
}
public override T Add(T entity)
{
AddedEntities.Add(entity);
_contentCollection.Add(entity);
return entity;
}
public override T Attach(T entity)
{
AttachedEntities.Add(entity);
var matchingEntity = _contentCollection.SingleOrDefault(x => x.Id == entity.Id);
if (matchingEntity != null)
{
_contentCollection.Remove(matchingEntity);
}
_contentCollection.Add(entity);
return entity;
}
public override TDerivedEntity Create<TDerivedEntity>()
{
throw new NotImplementedException();
}
public override T Create()
{
throw new NotImplementedException();
}
public override T Find(params object[] keyValues)
{
throw new NotImplementedException();
}
public override T Remove(T entity)
{
RemovedEntities.Add(entity);
_contentCollection.Remove(entity);
return entity;
}
}
You can use constructor parameter to setup content that will be retrieved by the db set.
Hope this helps.
I have the following code defined in terms of hierarchy -
public interface ISomeInterface
{
bool DoSomething();
}
public abstract class AbsActualWorker : ISomeInterface
{
public bool DoSomething()
{
Console.WriteLine("DoSomething");
throw new Exception("throwing exception for the sake of it!");
}
public abstract bool DoSomething2();
}
public class ActualWorker : AbsActualWorker
{
public override bool DoSomething2()
{
Console.WriteLine("DoSomething2");
Thread.Sleep(1000);
return true;
//throw new Exception("throwing exception for the sake of it!");
}
}
Im trying to resolve to the ActualWorker level and execute its DoSomething2
var container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterType<AbsActualWorker, ActualWorker>();
container
.RegisterType<ISomeInterface, ActualWorker>(new Interceptor(new InterfaceInterceptor()),
new InterceptionBehavior(new MyLoggerBehavior())
);
var instance = container.Resolve<ISomeInterface>();
if (instance != null)
{
instance.DoSomething();
}
Code happily resolves and can call
instance.DoSomething();
When I cast instance to ActualWorker Im getting null. Id like to use call DoSomething2.
public class MyLoggerBehavior : IInterceptionBehavior
{
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
var returnValue = getNext()(input, getNext);
if (returnValue.Exception != null)
{
Console.WriteLine("Exception occurred!!");
}
else
{
Console.WriteLine("Method {0} returned {1}", input.MethodBase, returnValue.ReturnValue);
}
return returnValue;
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public bool WillExecute
{
get { return true; }
}
}
Your problem is in interceptor. Due to
container.RegisterType<ISomeInterface, ActualWorker>(new Interceptor(new InterfaceInterceptor()), new InterceptionBehavior(new MyLoggerBehavior()));
You get for ISomeInterface not ActualWorker type but a wrappertype that realize ISomeInterface. This type cannot be casted to ActualWorker.
If you work with Dependency injection you should not call methods that is not in public interface that you inject. If you need to cast variable of interface to concrete realization it means that you do something wrong.
I'm trying to create a unit test for my service with a mocked DbContext. I created an interface IDbContext with the following functions:
public interface IDbContext : IDisposable
{
IDbSet<T> Set<T>() where T : class;
DbEntityEntry<T> Entry<T>(T entity) where T : class;
int SaveChanges();
}
My real context implements this interface IDbContext and DbContext.
Now I'm trying to mock the IDbSet<T> in the context, so it returns a List<User> instead.
[TestMethod]
public void TestGetAllUsers()
{
// Arrange
var mock = new Mock<IDbContext>();
mock.Setup(x => x.Set<User>())
.Returns(new List<User>
{
new User { ID = 1 }
});
UserService userService = new UserService(mock.Object);
// Act
var allUsers = userService.GetAllUsers();
// Assert
Assert.AreEqual(1, allUsers.Count());
}
I always get this error on .Returns:
The best overloaded method match for
'Moq.Language.IReturns<AuthAPI.Repositories.IDbContext,System.Data.Entity.IDbSet<AuthAPI.Models.Entities.User>>.Returns(System.Func<System.Data.Entity.IDbSet<AuthAPI.Models.Entities.User>>)'
has some invalid arguments
I managed to solve it by creating a FakeDbSet<T> class that implements IDbSet<T>
public class FakeDbSet<T> : IDbSet<T> where T : class
{
ObservableCollection<T> _data;
IQueryable _query;
public FakeDbSet()
{
_data = new ObservableCollection<T>();
_query = _data.AsQueryable();
}
public virtual T Find(params object[] keyValues)
{
throw new NotImplementedException("Derive from FakeDbSet<T> and override Find");
}
public T Add(T item)
{
_data.Add(item);
return item;
}
public T Remove(T item)
{
_data.Remove(item);
return item;
}
public T Attach(T item)
{
_data.Add(item);
return item;
}
public T Detach(T item)
{
_data.Remove(item);
return item;
}
public T Create()
{
return Activator.CreateInstance<T>();
}
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T
{
return Activator.CreateInstance<TDerivedEntity>();
}
public ObservableCollection<T> Local
{
get { return _data; }
}
Type IQueryable.ElementType
{
get { return _query.ElementType; }
}
System.Linq.Expressions.Expression IQueryable.Expression
{
get { return _query.Expression; }
}
IQueryProvider IQueryable.Provider
{
get { return _query.Provider; }
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _data.GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return _data.GetEnumerator();
}
}
Now my test looks like this:
[TestMethod]
public void TestGetAllUsers()
{
//Arrange
var mock = new Mock<IDbContext>();
mock.Setup(x => x.Set<User>())
.Returns(new FakeDbSet<User>
{
new User { ID = 1 }
});
UserService userService = new UserService(mock.Object);
// Act
var allUsers = userService.GetAllUsers();
// Assert
Assert.AreEqual(1, allUsers.Count());
}
In case anyone is still interested, I was having the same problem and found this article very helpful:
Entity Framework Testing with a Mocking Framework (EF6 onwards)
It only applies to Entity Framework 6 or newer, but it covers everything from simple SaveChanges tests to async query testing all using Moq (and a few of manual classes).
Thank you Gaui for your great idea =)
I did add some improvements to your solution and want to share it.
My FakeDbSet also inherents from DbSet to get additional methods
like AddRange()
I replaced the ObservableCollection<T> with List<T> to pass all
the already implemented methods in List<> up to my FakeDbSet
My FakeDbSet:
public class FakeDbSet<T> : DbSet<T>, IDbSet<T> where T : class {
List<T> _data;
public FakeDbSet() {
_data = new List<T>();
}
public override T Find(params object[] keyValues) {
throw new NotImplementedException("Derive from FakeDbSet<T> and override Find");
}
public override T Add(T item) {
_data.Add(item);
return item;
}
public override T Remove(T item) {
_data.Remove(item);
return item;
}
public override T Attach(T item) {
return null;
}
public T Detach(T item) {
_data.Remove(item);
return item;
}
public override T Create() {
return Activator.CreateInstance<T>();
}
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T {
return Activator.CreateInstance<TDerivedEntity>();
}
public List<T> Local {
get { return _data; }
}
public override IEnumerable<T> AddRange(IEnumerable<T> entities) {
_data.AddRange(entities);
return _data;
}
public override IEnumerable<T> RemoveRange(IEnumerable<T> entities) {
for (int i = entities.Count() - 1; i >= 0; i--) {
T entity = entities.ElementAt(i);
if (_data.Contains(entity)) {
Remove(entity);
}
}
return this;
}
Type IQueryable.ElementType {
get { return _data.AsQueryable().ElementType; }
}
Expression IQueryable.Expression {
get { return _data.AsQueryable().Expression; }
}
IQueryProvider IQueryable.Provider {
get { return _data.AsQueryable().Provider; }
}
IEnumerator IEnumerable.GetEnumerator() {
return _data.GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator() {
return _data.GetEnumerator();
}
}
It is very easy to modify the dbSet and Mock the EF Context Object:
var userDbSet = new FakeDbSet<User>();
userDbSet.Add(new User());
userDbSet.Add(new User());
var contextMock = new Mock<MySuperCoolDbContext>();
contextMock.Setup(dbContext => dbContext.Users).Returns(userDbSet);
Now it is possible to execute Linq queries, but be a aware that foreign key references may not be created automatically:
var user = contextMock.Object.Users.SingeOrDefault(userItem => userItem.Id == 42);
Because the context object is mocked the Context.SaveChanges() won't do anything and property changes of your entites might not be populated to your dbSet. I solved this by mocking my SetModifed() method to populate the changes.
Based on this MSDN article, I've created my own libraries for mocking DbContext and DbSet:
EntityFrameworkMock - GitHub
EntityFrameworkMockCore - GitHub
Both available on NuGet and GitHub.
The reason I've created these libraries is because I wanted to emulate the SaveChanges behavior, throw a DbUpdateException when inserting models with the same primary key and support multi-column/auto-increment primary keys in the models.
In addition, since both DbSetMock and DbContextMock inherit from Mock<DbSet> and Mock<DbContext>, you can use all features of the Moq framework.
Next to Moq, there also is an NSubstitute implementation.
Usage with the Moq version looks like this:
public class User
{
[Key, Column(Order = 0)]
public Guid Id { get; set; }
public string FullName { get; set; }
}
public class TestDbContext : DbContext
{
public TestDbContext(string connectionString)
: base(connectionString)
{
}
public virtual DbSet<User> Users { get; set; }
}
[TestFixture]
public class MyTests
{
var initialEntities = new[]
{
new User { Id = Guid.NewGuid(), FullName = "Eric Cartoon" },
new User { Id = Guid.NewGuid(), FullName = "Billy Jewel" },
};
var dbContextMock = new DbContextMock<TestDbContext>("fake connectionstring");
var usersDbSetMock = dbContextMock.CreateDbSetMock(x => x.Users, initialEntities);
// Pass dbContextMock.Object to the class/method you want to test
// Query dbContextMock.Object.Users to see if certain users were added or removed
// or use Mock Verify functionality to verify if certain methods were called: usersDbSetMock.Verify(x => x.Add(...), Times.Once);
}
If anyone is still looking for answers I've implemented a small library to allow mocking DbContext.
step 1
Install Coderful.EntityFramework.Testing nuget package:
Install-Package Coderful.EntityFramework.Testing
step 2
Then create a class like this:
internal static class MyMoqUtilities
{
public static MockedDbContext<MyDbContext> MockDbContext(
IList<Contract> contracts = null,
IList<User> users = null)
{
var mockContext = new Mock<MyDbContext>();
// Create the DbSet objects.
var dbSets = new object[]
{
MoqUtilities.MockDbSet(contracts, (objects, contract) => contract.ContractId == (int)objects[0] && contract.AmendmentId == (int)objects[1]),
MoqUtilities.MockDbSet(users, (objects, user) => user.Id == (int)objects[0])
};
return new MockedDbContext<SourcingDbContext>(mockContext, dbSets);
}
}
step 3
Now you can create mocks super easily:
// Create test data.
var contracts = new List<Contract>
{
new Contract("#1"),
new Contract("#2")
};
var users = new List<User>
{
new User("John"),
new User("Jane")
};
// Create DbContext with the predefined test data.
var dbContext = MyMoqUtilities.MockDbContext(
contracts: contracts,
users: users).DbContext.Object;
And then use your mock:
// Create.
var newUser = dbContext.Users.Create();
// Add.
dbContext.Users.Add(newUser);
// Remove.
dbContext.Users.Remove(someUser);
// Query.
var john = dbContext.Users.Where(u => u.Name == "John");
// Save changes won't actually do anything, since all the data is kept in memory.
// This should be ideal for unit-testing purposes.
dbContext.SaveChanges();
Full article: http://www.22bugs.co/post/Mocking-DbContext/
I'm late, but found this article helpful: Testing with InMemory (MSDN Docs).
It explains how to use an in memory DB context (which is not a database) with the benefit of very little coding and the opportunity to actually test your DBContext implementation.
I have a repository interface as below:
public interface IDataContext<TId> : IDisposable
{
IQueryable<T> Repository<T>() where T : class, IEntity<TId>;
T FindById<T>(TId id) where T : class, IEntity<TId>;
void Insert<T>(T item) where T : class, IEntity<TId>;
void Delete<T>(T item) where T : class, IEntity<TId>;
void Commit();
}
Note that Repository<T> returns an IQueryable<T>.
I have a class that can wrap a LinqToSQL data context, with the Repository<T> method as below:
public IQueryable<T> Repository<T>() where T : class, IEntity<int>
{
ITable table = _context.GetTable(GetEntityType<T>());
return table.Cast<T>();
}
This works fine, I can do something like
new Repository(new SQLDataContext())
.Repository<MyEntity>().Where(e => SqlMethods.Like(e.Id, "123%");
Now I've started thinking about caching but I have a problem.
I've created a class that wraps and implements an IDataContext<TId> that will cache results from calls to Repository<T> in memory. Something like the below:
public IQueryable<T> Repository<T>() where T : class, IEntity<TId>
{
// Actual caching logic here.....
return _CachedEntities[typeof(T)].OfType<T>().AsQueryable<T>();
}
The issue I have is that now the IQueryable<T> I return is in-memory, not translated to SQL, so I get an exception about using SqlMethods.Like.
TL;DR: So, how can I create my caching repository wrapper in such a way that the calling classes don't need to worry about whether the IDataContext<T> it's dealing with is an in-memory repository (i.e. the caching one) or a normal LinqToSQL repository?
It's possible, you need to write custom IQueryProvider and IQueryable<T>:
public static class MySqlMethods
{
public static bool Like(string matchExpression, string pattern)
{
//Your implementation
return true;
}
}
public class ChangeMethodsVisitor : ExpressionVisitor
{
//This method will change SqlMethods to MySqlMethods.
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.DeclaringType == typeof(SqlMethods))
{
//Getting method from MySqlMethods class.
var method = typeof(MySqlMethods).GetMethod(node.Method.Name,
node.Method.GetParameters()
.Select(info => info.ParameterType)
.ToArray());
return Expression.Call(method, node.Arguments);
}
return base.VisitMethodCall(node);
}
}
public class MyQueryProvider : IQueryProvider
{
private static readonly ExpressionVisitor ExpressionVisitor = new ChangeMethodsVisitor();
private readonly IQueryProvider _queryProvider;
public MyQueryProvider(IQueryProvider queryProvider)
{
_queryProvider = queryProvider;
}
public IQueryable CreateQuery(Expression expression)
{
expression = ExpressionVisitor.Visit(expression);
var queryable = _queryProvider.CreateQuery(expression);
//Wrap queryable to MyQuery class.
var makeGenericType = typeof(MyQuery<>).MakeGenericType(queryable.ElementType);
return (IQueryable)makeGenericType.GetConstructor(new[] { typeof(IQueryable<>).MakeGenericType(queryable.ElementType) })
.Invoke(new object[] { queryable });
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
expression = ExpressionVisitor.Visit(expression);
//Wrap queryable to MyQuery class.
var queryable = _queryProvider.CreateQuery<TElement>(expression);
return new MyQuery<TElement>(queryable);
}
public object Execute(Expression expression)
{
expression = ExpressionVisitor.Visit(expression);
return _queryProvider.Execute(expression);
}
public TResult Execute<TResult>(Expression expression)
{
expression = ExpressionVisitor.Visit(expression);
return _queryProvider.Execute<TResult>(expression);
}
}
public class MyQuery<T> : IOrderedQueryable<T>
{
private readonly IQueryable<T> _queryable;
public MyQuery(IQueryable<T> queryable)
{
_queryable = queryable;
Provider = new MyQueryProvider(_queryable.Provider);
}
public MyQuery(IEnumerable<T> enumerable)
: this(enumerable.AsQueryable())
{
}
public IEnumerator<T> GetEnumerator()
{
return _queryable.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public Expression Expression
{
get { return _queryable.Expression; }
}
public Type ElementType
{
get { return _queryable.ElementType; }
}
public IQueryProvider Provider { get; private set; }
}
And then you can use it:
var list = new List<string>(){"test", "test1"};
var myQuery = new MyQuery<string>(list);
var queryable = myQuery.Where(s => SqlMethods.Like(s, "123%")).ToArray();