I want generic/oneline statements for structuremap configuration . please see the following code and suggest the changes :
Structuremap configuration class :
class StructureMapTestConfigurationRegistry : Registry
{
/// <summary>
/// Initializes a new instance of the <see cref="DependencyConfigurationRegistry"/> class.
/// </summary>
public StructureMapTestConfigurationRegistry()
{
For<Repository.IRepository<Report>>().Use(MockObjectGenerator<Report>.RepositoryMockSetup());
For<Repository.IRepository<RelatedContent>>().Use(MockObjectGenerator<RelatedContent>.RepositoryMockSetup());
For<Repository.IRepository<Tags>>().Use(MockObjectGenerator<Tags>.RepositoryMockSetup());
For<Repository.IRepository<ArticleTag>>().Use(MockObjectGenerator<ArticleTag>.RepositoryMockSetup());
For<Repository.IRepository<ReferenceBookTag>>().Use(MockObjectGenerator<ReferenceBookTag>.RepositoryMockSetup());
For<Repository.IRepository<EventsTag>>().Use(MockObjectGenerator<EventsTag>.RepositoryMockSetup());
For<Repository.IRepository<CountryFactfileTag>>().Use(MockObjectGenerator<CountryFactfileTag>.RepositoryMockSetup());
}
BootStrapper Class :
public static class TestBootstrapper
{
public static void TestConfigureStructureMap()
{
ObjectFactory.Container.Dispose();
ObjectFactory.Initialize(o => o.AddRegistry(new StructureMapTestConfigurationRegistry()));
ObjectFactory.Container.AssertConfigurationIsValid();
}
}
MockObjectGenerator Class :
public static class MockObjectGenerator<TEntity> where TEntity : class
{
private static List<TEntity> DummyTable
{
get
{
return MockEntities.GetData<TEntity>();
}
}
public static IRepository<TEntity> RepositoryMockSetup()
{
Mock<IRepository<TEntity>> repository = new Mock<IRepository<TEntity>>(MockBehavior.Strict);
repository.Setup(o => o.Fetch(It.IsAny<Expression<Func<TEntity, bool>>>())).Returns((Expression<Func<TEntity, bool>> i) => DummyTable.Where(i.Compile()).ToList());
repository.Setup(o => o.Create(It.IsAny<IEnumerable<TEntity>>())).Callback<IEnumerable<TEntity>>(items => DummyTable.AddRange(items));
repository.Setup(o => o.Delete(It.IsAny<TEntity>())).Callback<TEntity>(item => DummyTable.Remove(item));
}
}
**Mock Entities Class :**
public static class MockEntities
{
public static Dictionary<string, dynamic> MockData = new Dictionary<string, dynamic>();
public static void LoadData()
{
MockData.Add(typeof(CMSModel.Article).Name, ArticleTestData.GetTestRecords());
MockData.Add(typeof(CMSModel.ArticleTag).Name, RelatedArticleContentTestData.GetTestRecords());
}
public static List<T> GetData<T>() where T : class
{
return (List<T>)MockData[typeof(T).Name];
}
}
Note :
This has been done so that in actual unit test , We dont have to write setup methods since that is done while creating dependent object using structuremap.
It works fine, but I want to refactor the configuration file code to generic
I have writen it for implentation like this :
For(typeof(Repository.IRepository<>)).Use(typeof(Repository.Repository<>));
is it possible for unit test configuration ?
It is possible, though you'd need to specify all types entity types that are going to be used and pass them as Types. And you'll need to use non-generic version of functions (to be able to write For(type) instead of For). That way all your functions would work only on type variables and would look like simple methods.
Related
I am using Entity Framework 6 and Moq framework. Currently I am writing a few Unit Tests where in each test I need to set up a dataset with the appropriate type for each test.
One of the unit tests looks like this:
[TestMethod]
public async Task GetAllCaseCategories_WithEmptyDataset_ReturnsEmpty()
{
var data = new List<DataAccessLayer.Tables.CaseCategory>(){};
var mockContext = GetMockContextWithCaseCategoryDataSetAsync(data);
var mockLogger = new Mock<IDatabaseContextLogging>();
DatabaseTablesAccess databaseAccess = new DatabaseTablesAccess(mockDatabaseContext.Object, mockLogger.Object);
List<OneCaseCategory> caseCategories = await databaseAccess.GetAllCaseCategories();
Assert.IsTrue(caseCategories.Count().Equals(0), "caseCategories should not contain any items.");
}
The method that generates the database context mock object is contain in the method called "GetMockContextWithCaseCategoryDataSetAsync". Here it is:
public Mock<Context> GetMockContextWithCaseCategoryDataSetAsync(List<CaseCategory> data)
{
var mockCaseCategorySet = new Mock<DbSet<CaseCategory>>() { };
mockCaseCategorySet.As<IQueryable<CaseCategory>>().Setup(x => x.Provider).Returns(new TestDbAsyncQueryProvider<CaseCategory>(data.AsQueryable().Provider));
mockCaseCategorySet.As<IQueryable<CaseCategory>>().Setup(x => x.Expression).Returns(data.AsQueryable().Expression);
mockCaseCategorySet.As<IQueryable<CaseCategory>>().Setup(x => x.ElementType).Returns(data.AsQueryable().ElementType);
mockCaseCategorySet.As<IDbAsyncEnumerable<CaseCategory>>().Setup(x => x.GetAsyncEnumerator()).Returns(new TestDbAsyncEnumerator<CaseCategory>(data.AsQueryable().GetEnumerator()));
mockCaseCategorySet.As<IQueryable<CaseCategory>>().Setup(x => x.GetEnumerator()).Returns(data.AsQueryable().GetEnumerator());
Mock<Context> m = new Mock<Context>();
m.Setup(x => x.CaseCategories).Returns(mockCaseCategorySet.Object);
return m;
}
I have multiple tables in the data access object and I have written a method for each one that returns the data access object with the appropriate type of data bound to the correct table in the mock object. I would like to generalize this and here is my attempt:
public Mock<Context> GetMockContextWithCaseCategoryDataSetAsync<T>(List<T> data) where T : class
{
var mockCaseCategorySet = new Mock<DbSet<T>>() { };
mockCaseCategorySet.As<IQueryable<T>>().Setup(x => x.Provider).Returns(new TestDbAsyncQueryProvider<T>(data.AsQueryable().Provider));
mockCaseCategorySet.As<IQueryable<T>>().Setup(x => x.Expression).Returns(data.AsQueryable().Expression);
mockCaseCategorySet.As<IQueryable<T>>().Setup(x => x.ElementType).Returns(data.AsQueryable().ElementType);
mockCaseCategorySet.As<IDbAsyncEnumerable<T>>().Setup(x => x.GetAsyncEnumerator()).Returns(new TestDbAsyncEnumerator<T>(data.AsQueryable().GetEnumerator()));
mockCaseCategorySet.As<IQueryable<T>>().Setup(x => x.GetEnumerator()).Returns(data.AsQueryable().GetEnumerator());
Mock<Context> m = new Mock<Context>();
m.Setup(x => x.?).Returns(mockCaseCategorySet.Object);
return m;
}
Everything is good up until that second last line in the generic version of the method where I am setting up which table returns the mocked object. I am lost as to how (if even possible) I control which table is used based on the generic passed in.
I would like to use it like this:
var context = GetMockContextWithCaseCategoryDataSetAsync<CaseCategory>(data);
I don't see a way to do what you're trying to do unless you also access the DbSets by the generic Set<TEntity> method (like _dbContext.Set<Salary>().Select(x => x.Id)).
An alternative setup that I have been using and that is sort of generic is to create a "MockedDbContext" class that I reuse in all tests accessing the database. This usually looks something like this;
public class MockedDbContext
{
public MockedDbContext() => MockContextProperties();
public Mock<MyDbContext> ContextMock { get; } = new Mock<MyDbContext>(MockBehavior.Loose);
public HashSet<Employee> Employees { get; } = new HashSet<Employee>();
public HashSet<Salary> Salaries { get; } = new HashSet<Salary>();
// etc...
private void MockContextProperties()
{
SimulateGet(x => x.Employees, Employees);
SimulateGet(x => x.Salaries, Salaries);
// etc...
}
private void SimulateGet<TModel>(
Expression<Func<MyDbContext, DbSet<TModel>>> dbSetExpression,
HashSet<TModel> mockedData) where TModel : class
{
ContextMock.SetupGet(dbSetExpression).Returns(new InMemoryDbSet<TModel>(mockedData));
}
public void VerifyThatSaveWasCalled() => ContextMock.Verify(x => x.SaveChanges());
public void VerifyThatSaveWasNotCalled() => ContextMock.Verify(x => x.SaveChanges(), Times.Never);
}
I use it like this;
[TestFixture]
public class When_getting_some_data
{
private readonly MockedDbContext _mockedDbContext = new MockedDbContext();
private readonly Fixture _fixture = new Fixture();
private string _organizationNumber = "yyyyyy-xxx";
private readonly DateTime _created = new DateTime(2022, 2, 2);
private SomeInformation _result;
[OneTimeSetUp]
public void Initialize()
{
var salary = _fixture.Build<Salary>().With(o => o.Created, _created).Create();
_mockedDbContext.Salaries.Add(salary);
_result = new SomeClass(_mockedDbContext.ContextMock.Object).GetSomeInformation(_organizationNumber);
}
[Test]
public void Then_returned_data_is_as_expected()
{
_result.Should().NotBeNull();
_result.Created.Should().Be(_created);
}
}
And It internally uses an InMemoryDbSet<T> that looks like this;
/// <summary>
/// The in-memory database set, taken from Microsoft's online example (http://msdn.microsoft.com/en-us/ff714955.aspx)
/// and modified to be based on DbSet instead of ObjectSet.
/// </summary>
/// <typeparam name="T">The type of DbSet.</typeparam>
public class InMemoryDbSet<T> : DbSet<T>, IQueryable<T> where T : class
{
private static readonly HashSet<T> StaticData = new HashSet<T>();
private readonly HashSet<T> _nonStaticData;
/// <summary>
/// Creates an instance of the InMemoryDbSet using the default static backing store.This means
/// that data persists between test runs, like it would do with a database unless you
/// cleared it down.
/// </summary>
public InMemoryDbSet() : this(true) { }
/// <summary>
/// This constructor allows you to pass in your own data store, instead of using
/// the static backing store.
/// </summary>
/// <param name="data">A place to store data.</param>
public InMemoryDbSet(HashSet<T> data) => _nonStaticData = data;
/// <summary>
/// Creates an instance of the InMemoryDbSet using the default static backing store.This means
/// that data persists between test runs, like it would do with a database unless you
/// cleared it down.
/// </summary>
/// <param name="clearDownExistingData">True to clear existing data</param>
public InMemoryDbSet(bool clearDownExistingData)
{
if (clearDownExistingData)
Clear();
}
public Func<IEnumerable<T>, object[], T> FindFunction { get; set; }
public Type ElementType => Data.AsQueryable().ElementType;
public Expression Expression => Data.AsQueryable().Expression;
public IQueryProvider Provider => Data.AsQueryable().Provider;
IQueryProvider IQueryable.Provider => Data.AsQueryable().Provider;
public new ObservableCollection<T> Local => new ObservableCollection<T>(Data);
/// <summary>
/// The non static backing store data for the InMemoryDbSet.
/// </summary>
private HashSet<T> Data => _nonStaticData ?? StaticData;
public void Clear() => Data.Clear();
public override EntityEntry<T> Add(T entity)
{
Data.Add(entity);
return null;
}
public new T Attach(T entity)
{
Data.Add(entity);
return entity;
}
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T => Activator.CreateInstance<TDerivedEntity>();
public T Create() => Activator.CreateInstance<T>();
public new virtual T Find(params object[] keyValues)
{
if (FindFunction != null)
{
return FindFunction(Data, keyValues);
}
throw new NotImplementedException("Derive from InMemoryDbSet and override Find, or provide a FindFunction.");
}
public new T Remove(T entity)
{
Data.Remove(entity);
return entity;
}
public IEnumerator<T> GetEnumerator() => Data.GetEnumerator();
}
This saves a lot of work when writing unit tests and is kind of a one time setup which is what I think you were looking for.
How can I register an Open Generic type with another open generic and primitive injected in the constructor?See example below.In this example, Resolve is throwing "Unable to resolve String as parameter "connectionString"" exception. (you can check live code here)
using System;
using DryIoc;
public class Program
{
public static void Main()
{
var container = new Container();
container.RegisterInstance("some_connection_string", serviceKey: "connectionString");
container.Register(typeof(Configuration<>), Reuse.Singleton);
container.Register(typeof (IEntityUpdater<>), typeof (SqlEntityUpdater<>), Reuse.Singleton);
var p = container.Resolve<IEntityUpdater<EventArgs>>();
Console.WriteLine(p);
}
}
public class Configuration<T> where T : class { }
internal interface IEntityUpdater<in T> where T : class
{
void Update(T entity);
}
internal class SqlEntityUpdater<T> : IEntityUpdater<T> where T : class
{
public SqlEntityUpdater(Configuration<T> configuration, string connectionString)
{
}
public void Update(T entity) { }
}
First, RegisterInstance is depricated, use UseInstance.
Second, the actual problem is that you registering instance with serviceKey and nowhere using this key for injection.
So, you either remove the serviceKey parameter.
Or, specify the key on injection side:
container.Register(typeof(IEntityUpdater<>), typeof(SqlEntityUpdater<>), Reuse.Singleton,
made: Parameters.Of.Type<string>(serviceKey: "connectionString"));
I am using Fluent NHibernate and trying to do unit testing. Now I have a base test class which looks as follows:
[TestClass]
public abstract class BaseTest<TEntity> where TEntity : IBaseModel
{
private const string testDbFile = "test.db";
private static ISessionFactory sessionFactory;
protected static ISession session;
[TestMethod]
public void configureDB()
{
try
{
if (sessionFactory == null)
{
sessionFactory = Fluently.Configure()
.Database(SQLiteConfiguration.Standard
.UsingFile(testDbFile))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<AdminTest>())
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException.Message);
}
}
private static void BuildSchema(Configuration config)
{
new SchemaUpdate(config).Execute(false, true);
}
[TestMethod]
public void sessionCreated()
{
session = sessionFactory.OpenSession();
}
[TestMethod]
public virtual void AddEntity_EntityWasAdded()
{
var entity = BuildEntity();
InsertEntity(entity);
session.Evict(entity);
var reloadedEntity = session.Get<TEntity>(entity.Id);
Assert.IsNotNull(reloadedEntity);
AssertAreEqual(entity, reloadedEntity);
AssertValidId(reloadedEntity);
}
There are also other methods which update and delete an entity. And I have AdminTest class which inherits BaseTest. In AdminTest I have following method:
[TestClass]
public class AdminTest : BaseTest<Admin>
{
[TestMethod]
public void SelectWorks()
{
IList<Admin> admins = session.QueryOver<Admin>().List();
Assert.AreNotEqual(0, admins.Count);
}
}
Here I always have exception, because session is null. Maybe I am wrong in the way of thinking how visual studio performs unit tests (I am newbie in it)?
Now I think like that, visual studio works in the following way
runs test-methods from BaseTest (there it configures database and creates session)
runs selectWorks method. Here I was thinking it should use session from BaseTest
Could you explain what is wrong in my way of thinking? And I want to be able to query from child classes, what is the right way of doing it?
Thanks, any help is appreciated, .
I would suggest using [TestInitialize] and [TestCleanup] in your abstract base class and doing something like the following:
[TestInitialize]
public void TestInitialize()
{
Console.Out.WriteLine("Get a ISession object");
}
[TestCleanup]
public void TestCleanup()
{
Console.Out.WriteLine("Dispose ISession");
}
Then in your child classes continue to do what you are doing:
[TestMethod]
public void DoDbWork()
{
Console.Out.WriteLine("Running a query via nhibernate");
}
You really just want to ensure you have a clean session for each test. The attributes for TestInitialize and TestCleanup will run before and after each unit test. Here is the documentation for those attributes.
To ensure your ISession is in the right state,follow something like this.
I have been given the task to evaluate codeFirst and possible to use for all our future projects.
The evaluation is based on using codeFirst with an existing database.
Wondering if it's possible to mock the repository using codeFirst 4.1.(no fakes)
The idea is to inject a repository into a service and moq the repository.
I have been looking on the net but I have only found an example using fakes.I dont want to use fakes I want to use moq.
I think my problem is in the architecture of the DAL.(I would like to use unitOfWork etc.. by I need to show a working moq example)
Below is my attempt(Failed miserably) due to lack of knowledge on Code first 4.1.
I have also uploaded a solution just in case somebody is in good mood and would like to change it.
http://cid-9db5ae91a2948485.office.live.com/browse.aspx/Public%20Folder?uc=1
I am open to suggestions and total modification to my Dal.Ideally using Unity etc.. but I will worry about later.
Most importantly I need to be able to mock it. Without ability to use MOQ we will bin the project using EF 4.1
Failed attempt
//CodeFirst.Tests Project
[TestClass]
public class StudentTests
{
[TestMethod]
public void Should_be_able_to_verify_that_get_all_has_been_called()
{
//todo redo test once i can make a simple one work
//Arrange
var repository = new Mock<IStudentRepository>();
var expectedStudents = new List<Student>();
repository.Setup(x => x.GetAll()).Returns(expectedStudents);
//act
var studentService = new StudentService(repository.Object);
studentService.GetAll();
//assert
repository.Verify(x => x.GetAll(), Times.AtLeastOnce());
}
}
//CodeFirst.Common Project
public class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
public interface IStudentService
{
IEnumerable<Student> GetAll();
}
//CodeFirst.Service Project
public class StudentService:IStudentService
{
private IStudentRepository _studentRepository;
public StudentService()
{
}
public StudentService(IStudentRepository studentRepository)
{
_studentRepository = studentRepository;
}
public IEnumerable<Student> GetAll()
{
//TODO when mocking using moq this will actually call the db as we need a separate class.
using (var ctx = new SchoolContext("SchoolDB"))
{
_studentRepository = new StudentRepository(ctx);
var students = _studentRepository.GetAll().ToList();
return students;
}
}
}
//CodeFirst.Dal Project
public interface IRepository<T> where T : class
{
T GetOne(Expression<Func<T, bool>> predicate);
IEnumerable<T> GetAll();
IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
void Add(T entity);
void Delete(T entity);
T Single(Func<T, bool> predicate);
T First(Func<T, bool> predicate);
}
public class RepositoryBase<T> : IRepository<T> where T : class
{
private readonly IDbSet<T> _dbSet;
public RepositoryBase(DbContext dbContext)
{
_dbSet = dbContext.Set<T>();
if (_dbSet == null) throw new InvalidOperationException("Cannot create dbSet ");
}
protected virtual IDbSet<T> Query
{
get { return _dbSet; }
}
public T GetOne(Expression<Func<T, bool>> predicate)
{
return Query.Where(predicate).FirstOrDefault();
}
public IEnumerable<T> GetAll()
{
return Query.ToArray();
}
public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
{
return Query.Where(predicate).ToArray();
}
public void Add(T entity)
{
_dbSet.Add(entity);
}
public void Delete(T entity)
{
_dbSet.Remove(entity);
}
public T Single(Func<T, bool> predicate)
{
return Query.Where(predicate).SingleOrDefault();
}
public T First(Func<T, bool> predicate)
{
return Query.Where(predicate).FirstOrDefault();
}
}
public class SchoolContext:DbContext
{
public SchoolContext(string connectionString):base(connectionString)
{
Database.SetInitializer<SchoolContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Not sure why I have to do this.Without this when using integration testing
//as opposed to UnitTests it does not work.
modelBuilder.Entity<Student>().ToTable("Student"); }
public DbSet<Student> Students { get; set; }
}
public interface IStudentRepository:IRepository<Student>
{
}
public class StudentRepository : RepositoryBase<Student>, IStudentRepository
{
public StudentRepository(DbContext dbContext)
: base(dbContext)
{
}
public IEnumerable<Student> GetStudents()
{
return GetAll();
}
}
Again feel free to modify or whatever is needed to help me to get something together.
Thanks a lot for your help
When I started with repository and unit of work patterns I used the implementation similar to this (it is for ObjectContext API but converting it to DbContext API is simple). We used that implementation with MOQ and Unity without any problems. By the time implementations of repository and unit of work have evolve as well as the approach of injecting. Later on we found that whole this approach has serious pitfalls but that was alredy discussed in other questions I referenced here (I highly recommend you to go through these links).
It is very surprising that you are evaluating the EFv4.1 with high emphasis on mocking and unit testing and in the same time you defined service method which is not unit-testable (with mocking) at all. The main problem of you service method is that you are not passing repository/context as dependency and because of that you can't mock it. The only way to test your service and don't use the real repository is using some very advanced approach = replacing mocking and MOQ with detouring (for example Moles framework).
First what you must do is replacing your service code with:
public class StudentService : IStudentService
{
private readonly IStudentRepository _studentRepository;
public StudentService(IStudentRepository studentRepository)
{
_studentRepository = studentRepository;
}
public IEnumerable<Student> GetAll()
{
return _studentRepository.GetAll().ToList();
}
}
Btw. this is absolutely useless code and example of silly layering which doesn't offer any useful functionality. Just wrapping the call to repository only shows that service is not needed at all as well as unit testing this method is not needed. The main point here is integration test for GetAll method.
Anyway if you want to unit thest such method with MOQ you will do:
[TestClass]
public class StudentsServiveTest
{
private Mock<IRespository<Student>> _repo;
[TestInitialize]
public void Init()
{
_repo = new Mock<IRepository<Student>>();
_repo.Setup(r => r.GetAll()).Returns(() => new Student[]
{
new Student { StudentId = 1, Name = "A", Surname = "B" },
new Student { StudentId = 2, Name = "B", Surname = "C" }
});
}
[TestMethod]
public void ShouldReturnAllStudents()
{
var service = new StudentsService(_repo.Object);
var data = service.GetAll();
_repo.Verify(r => r.GetAll(), Times.Once());
Assert.IsNotNull(data);
Assert.AreEqual(2, data.Count);
}
}
The issue from what I can see is that you are throwing away the mock object and newing up a new instance
_studentRepository = new StudentRepository(ctx);
Perhaps add a method on the interface to add the context object and reuse the same instance that was injected in the constructor.
using (var ctx = new SchoolContext("SchoolDB"))
{
_studentRepository.Context = ctx;
var students = _studentRepository.GetAll().ToList();
return students;
}
}
I'm trying to get Figure 3 Fake Database from IRepository using the example here
http://msdn.microsoft.com/en-us/magazine/dd263069.aspx
public class InMemoryRepository : IRepository
{
private readonly Cache<Type, object> _types;
private MockUnitOfWork _lastUnitOfWork;
public InMemoryRepository()
{
_types = new Cache<Type, object>(type =>
{
Type listType = typeof(List<>).MakeGenericType(type);
return Activator.CreateInstance(listType);
});
}
private IList<T> listFor<T>()
{
return (IList<T>)_types.Get(typeof(T));
}
public T Find<T>(long id) where T : Entity
{
return listFor<T>().FirstOrDefault(t => t.Id == id);
}
public void Delete<T>(T target)
{
listFor<T>().Remove(target);
}
public T[] Query<T>(Expression<Func<T, bool>> where)
{
var query = from item in listFor<T>() select item;
return query.Where(where.Compile()).ToArray();
}
public void Save<T>(T target)
{
listFor<T>().Add(target);
}
}
I'm getting 'Cannot resolve symbol MockUnitOfWork.
I have NUnit/Moq/Rhino.Mock installed/referenced but I cannot find any reference to MockUnitOfWork.
Any help appreciated.
You can just remove the MockUnitOfWork, because it is never used in the code.
I think it is a remnant left over after a refactoring.
The article doesn't explicitly say anything about what MockUnitOfWork is, but since it is an explicitly declared type, it must be a hand-rolled Mock.
Despite its semantic equivalence, it has nothing to do with Moq or RhinoMocks.
If you can download the source code for the article, I'm pretty sure you will find a class called MockUnitOfWork in the test project.