In a few words. Wpf app, ef used. I need to test model behavior using mock and unity. Unity and mock seem to me to be clear.
The question is following:
Model doesn't get the context through it constructor. It uses the context while execute the methods like this:
public Toys[] Get()
{
using (Context context = new Context())
{
return context.Toys.ToArray();
}
}
This is how I try to test:
[TestClass]
public class TestToyModel
{
[TestMethod]
public void TestToyCreate()
{
List<Toy> toys = new List<Toy>();
toys.Add(new Toy{ Id = "1234", Name = "Toy1" });
DbSet<Toy> dbToys = GetQueryableMockDbSet(toys);
Mock<ToyModel> model = new Mock<ToyModel>();
Mock<Context> context = new Mock<Context>();
context.Setup(x => x.Toys).Returns(dbToys);
//it' s all for now
}
private static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class
{
var queryable = sourceList.AsQueryable();
var dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s));
return dbSet.Object;
}
}
How can I supply my mock model with mock context ?
The context is being created manually so the class is tightly coupled to context which makes it difficult to unit test in isolation.
context is a dependency. abstract it out so that it can be mocked and injected into the subject under test.
public interface IContext : IDisposable {
public DbSet<Toy> Toys { get; }
//...other properties and methods
}
public class Context : DbContext, IContext {
public Context() { ... }
public DbSet<Toy> Toys { get; set; }
//...other properties and methods
}
Assuming system under test
public class ToyModel {
private readonly IContext context;
public MyClass(IContext context) {
this.context = context;
}
public Toys[] Get() {
return context.Toys.ToArray();
}
public void Create(Toy toy) {
context.Toys.Add(toy);
context.SaveChanges();
}
}
The class is no longer responsible for creating the dependency. That responsibility is now passed/delegated out to another class. Also note that your classes should depend on abstractions and not on concretions. This allows for more flexibility when swapping implementations. Like mocking for unit tests.
Now the context can be mocked and injected into the dependent class. Here is a simple example based on what you have done so far.
[TestClass]
public class TestToyModel {
[TestMethod]
public void TestToyCreate() {
//Arrange
var toys = new List<Toy>();
toys.Add(new Toy { Id = "1234", Name = "Toy1" });
var dbToys = GetQueryableMockDbSet(toys); //DbSet<Toy>
var contextMock = new Mock<IContext>();
contextMock.Setup(x => x.Toys).Returns(dbToys);
var sut = new ToyModel(contextMock.Object);
//Act
sut.Create(new Toy { Id = "5678", Name = "Toy2" });
//Assert
var expected = 2;
var actual = toys.Count;
Assert.AreEqual(expected, actual);
}
//...other code removed for brevity
}
If the ToyModel is the system under test, there is no need to mock it. Create an instance and pass the mocked dependencies to satisfy the test.
Related
I have a Repository pattern that interacts with Entity Framework.
I'd like to run some unit tests on the repository, and for this reason, I would like to mock DbContext.
So I've created a unit test project (.Net Core 3.1), using Moq as package for unit testing, everything seems to be ok, but when I perform a .ToListAsync() on my repository it throws the following exception:
System.NotImplementedException : The method or operation is not
implemented. Stack Trace:
IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken)
ConfiguredCancelableAsyncEnumerable1.GetAsyncEnumerator() EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable1
source, CancellationToken cancellationToken)
The source code:
public class Customer
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class CustomersDbContext : DbContext
{
public virtual DbSet<Customer> Customers { get; set; }
public CustomersDbContext(DbContextOptions<Customer> options) : base(options) { }
}
public interface ICustomerRepository
{
Task<IEnumerable<Customer>> GetCustomersAsync(Guid? customerId);
}
public class CustomerRepository : ICustomerRepository
{
private readonly CustomersDbContext _dbContext;
public CustomerRepository(CustomersDbContext dbContext)
{
_dbContext = dbContext;
_dbContext.Database.EnsureCreated();
}
public async Task<IEnumerable<Customer>> GetCustomersAsync(Guid? customerId)
{
IEnumerable<Customer> customers = null;
if (customerId.HasValue)
{
var customer = await _dbContext.Customers.FindAsync(new object[] { customerId.Value }, CancellationToken.None);
if (customer != null)
customers = new List<Customer>() { customer };
}
else
{
customers = await _dbContext.Customers.ToListAsync(CancellationToken.None);
}
return customers;
}
}
public class CustomerServiceUnitTests
{
private Mock<CustomersDbContext> GetCustomerDbContextMock()
{
var data = new List<Customer>()
{
new Customer()
{
Id = Guid.NewGuid(),
Name = "Name 1"
},
new Customer()
{
Id = Guid.NewGuid(),
Name = "Name 2"
}
}.AsQueryable();
var mockSet = new Mock<DbSet<Customer>>();
mockSet.As<IQueryable<Customer>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Customer>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Customer>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Customer>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
var optionsBuilder = new DbContextOptions<CustomersDbContext>();
var mockContext = new Mock<CustomersDbContext>(optionsBuilder);
Mock<DatabaseFacade> databaseFacade = new Mock<DatabaseFacade>(mockContext.Object);
databaseFacade.Setup(d => d.EnsureCreatedAsync(CancellationToken.None)).Returns(Task.FromResult(true));
mockContext.Setup(c => c.Database).Returns(databaseFacade.Object);
mockContext.Setup(c => c.Customers).Returns(mockSet.Object);
return mockContext;
}
[Fact]
public async Task Infrastructure_CustomerRepository_GetAll()
{
var mockContext = this.GetCustomerDbContextMock();
ICustomerRepository customerRepository = new CustomerRepository(mockContext.Object);
var customers = await customerRepository.GetCustomersAsync(null);
Assert.NotNull(customers);
Assert.Equal(2, customers.Count());
}
}
If I send an ID filled to the repository it works fine, so this seems to be not ok only for .ToListAsync().
I'm kinda stuck here, what can I do to overcome this?
You cannot mock DbSet query functionality. This is explained in the docs:
Properly mocking DbSet query functionality is not possible, since queries are expressed via LINQ operators, which are static
extension method calls over IQueryable. As a result, when some
people talk about "mocking DbSet", what they really mean is that they
create a DbSet backed by an in-memory collection, and then evaluate
query operators against that collection in memory, just like a simple
IEnumerable. Rather than a mock, this is actually a sort of fake,
where the in-memory collection replaces the the real database.
In order to execute Asynchronous read operation (ToListAsync()) you need to mock an additional interface called "IDBAsyncQueryProvider".
Here's is the required link you can follow. It is under the heading "Testing with async queries"
I am needing to set up a Unit Test for our project. In our Controllers we are using a Unit of Work which holds all the repositories and calling the repository in our IHttpActionResult to get the data.
So far I have set up a Mock of the Interfaces and this is calling the correct IHttpActionResult in the Controller but there is no data coming back.
[TestMethod]
public void TestMethod1()
{
var unitOfWork = new Mock<IUnitOfWork>();
var repo = new Mock<IAuditReleaseRepository>();
unitOfWork.Setup(e => e.AuditReleaseRepository).Returns(repo.Object);
var auditReleaseController = new AuditReleaseController(unitOfWork.Object);
var result = auditReleaseController.Get() as ViewResult;
var model = result.ViewData.Model as IQueryable<AuditReleas>;
Assert.AreEqual(12, model.Count());
}
public class AuditReleaseController : BaseController
{
private IAuditReleaseRepository _auditReleaseRepository;
private IUnitOfWork _unitOfWork;
public AuditReleaseController(IUnitOfWork unitOfWork)
{
this._unitOfWork = unitOfWork;
this._auditReleaseRepository = unitOfWork.AuditReleaseRepository;
}
[HttpGet, Route("audit-releases")]
public IHttpActionResult Get()
{
var query = this._auditReleaseRepository.GetAll();
return Ok(query);
}
}
public class AuditReleaseRepository : RepositoryBase<AuditReleas>, IAuditReleaseRepository
{
private readonly RetailAssignmentEntities _entities;
public AuditReleaseRepository(RetailAssignmentEntities entities) : base(entities)
{
this._entities = entities;
}
IEnumerable<AuditReleaseDto> IDtoRepository<AuditReleaseDto>.GetAll()
{
return base.GetAll().Where(x=>x.IsReleaseEnabled).Select(AuditReleaseMapping.All).OrderByDescending(x => x.Id);
}
}
This is the Mapping that is taking place to get the data in the GetAll method:
public class AuditReleaseMapping
{
public static Expression<Func<AuditReleas, AuditReleaseDto>> All = (auditRelease) => new AuditReleaseDto()
{
EndDate = auditRelease.AuditReleaseEndDate,
Id = auditRelease.AuditReleaseId,
Name = auditRelease.AuditReleaseName,
StartDate = auditRelease.AuditReleaseStartDate,
AuditPeriodId = auditRelease.AuditPeriod.AuditPeriodId,
AuditYearId = auditRelease.AuditPeriod.AuditYear.AuditYearId,
AuditEndDate = auditRelease.AuditPeriod.AuditEndDate,
AuditStartDate = auditRelease.AuditPeriod.AuditStartDate
};
}
What would be ideal is to call the Controller, which would call the repository, which would then call the Mapping but so far it's not even calling the Repository to get the data. I need help getting that functionality set up.
It looks like you need to Setup the behavior for your Mock repo.GetAll(). You will need to create a list of AuditReleaseDto's for your Mocked repo to return. Call it TestAuditReleaseDtos. You can create this TestData in the beginning of your TestMethod or in the TesstClass initialization. Then use it in a line right after creating your Mock:
var repo = new Mock<IAuditReleaseRepository>();
repo.Setup(r => r.GetAll()).Returns(TestAuditReleaseDtos);
unitOfWork.Setup(e => e.AuditReleaseRepository).Returns(repo.Object);
I have the following classes
namespace Foo.Bar.Services
{
public abstract class Service
{
public Service(IUnitOfWork unitOfWork)
{
this.UnitOfWork = unitOfWork;
}
protected IUnitOfWork UnitOfWork { get; private set; }
}
}
using...
namespace Foo.Bar.Services
{
public class ControlService : Service
{
...
private readonly IRepository<GroupStructure> groupStructures = null;
public ControlService(IUnitOfWork uow) : base(uow)
{
...
this.agencyGroupStructures = this.UnitOfWork.GetRepository<AgencyGroupStructure>();
}
public Tuple<bool, int> HasExternalImage(int branchId)
{
var externalResultList = from a in this.Structures.Table
where a.GroupID == branch.GroupID
&& (a.AreExternalRequired == true)
&& (a.ProductTypeID == ETourType.Trailer)
&& !a.Deleted
select a;
return (some logic based on above...)
}
}
and test
namespace ControlTests
{
[TestFixture]
public class Control
{
//unable to create service due to being abstact
[Test]
public void TestMethod1()
{
******Changed here******
var Mock = new Mock<GroupStructureService> { CallBase = true };
var fakeControl = new ControlService(Mock.Object)
var sut = fakeControl.HasExternalImage(1249);
Assert.That(sut.Item1, "true");
}
}
}
Running the above with NUnit and Moq gives the following message:
Castle.DynamicProxy.InvalidProxyConstructorArgumentsException : Can
not instantiate proxy of class: Foo.Bar.Services.ControlService.
Could not find a parameterless constructor.
I've tried a few things but I can't get this previously untested app to create a mock object to test
Edit, thanks. So I've changed it to use the ControlService and mock 1
dependancy. But its error is that it cant convert from
....GroupStructure to Foo.Bar.IUnitOfWork
Normally, the system under test is not mocked. Mock its dependencies and inject that into an instance of the class under test
[TestFixture]
public class Control {
[Test]
public void TestMethod1() {
//Arrange
var repository = new Mock<IRepository<GroupStructure>>();
//...Set up the repository behavior to satisfy logic
var uow = new Mock<IUnitOfWork>();
uow.Setup(_ => _.GetRepository<AgencyGroupStructure>())
.Returns(repository.Object);
var sut = new ControlService(uow.Object);
var expected = true;
//Act
var actual = sut.HasExternalImage(1249);
//Assert
Assert.AreEqual(actual.Item1, expected);
}
}
Reference Moq Quickstart to get a better understanding of how to use the mocking framework.
I have implemented generic repository in my project. Now I am writing test cases for my consumer. I am trying to mock database function through Moq but I am getting values from database rather than the one I faked through Moq. Below I am sharing my implementation. Hoping someone will help me in pointing out the mistake I made.
My interface:
public interface IEventsRepository<T> : IRepository<T> {
T GetEventsByEventId(int eventId); }
My class:
public class EventsTableRepository : EFDBRepository<EventsModel>, IEventsRepository<EventsModel> {
public EventsModel GetEventsByEventId(int eventId)
{
return _dbSet.Where(x => x.EventID == eventId).FirstOrDefault();
}
}
My Consumer:
public static Response<string> EventsAccept(EventsAlertsRequest logMsgId)
{
IEventsRepository<EventsModel> eventsRepo = (IEventsRepository<EventsModel>)RepositoryLocator.GetRepositoryObject(STMEnums.RepositoryName.EventsTableRepository.ToString());
EventsModel eventmodel = new EventsModel();
eventmodel = eventsRepo.GetEventsByEventId(eachlogMsgId);
return EventStatusChangeResponse;
}
Test Method:
public void EventsAcceptSuccessTest()
{
EventsModel eventmodel = new EventsModel();
eventmodel.Message = "TEST";
Mock<IEventsRepository<EventsModel>> obj = new Mock<IEventsRepository<EventsModel>>();
obj.Setup(m => m.GetEventsByEventId(Moq.It.IsAny<int>())).Returns(eventmodel);
EventStatusChangeResponse = Diagnostics_.EventsAccept(logMsgId);
Assert.AreEqual(eventmodel.Status, EventStatus.ACCEPTED);
}
No where in the provided example is the mock being injected into the subject under test. Also it looks like the subject method under test is using static Service Locator anti-pattern to get the desired model. Making an assumption here as the rest of the class is not shown in relation to that variable.
The locator would need to have been an injected abstraction to allow an opportunity to mock its expected behavior
public class Consumer {
private IRepositoryLocator RepositoryLocator;
public Consumer(IRepositoryLocator RepositoryLocator) {
this.RepositoryLocator = RepositoryLocator;
}
public Response<string> EventsAccept(EventsAlertsRequest logMsgId) {
IEventsRepository<EventsModel> eventsRepo = (IEventsRepository<EventsModel>)RepositoryLocator.GetRepositoryObject(STMEnums.RepositoryName.EventsTableRepository.ToString());
EventsModel eventmodel = new EventsModel();
eventmodel = eventsRepo.GetEventsByEventId(eachlogMsgId);
return EventStatusChangeResponse;
}
}
This would then mean that the locator would also have to be mocked properly for the test to be exercised to completion.
public void EventsAcceptSuccessTest() {
//Arrange
var eventmodel = new EventsModel() {
Message = "TEST"
};
var repositoryMock = new Mock<IEventsRepository<EventsModel>>();
repositoryMock
.Setup(_ => _.GetEventsByEventId(It.IsAny<int>()))
.Callback((int id) => {
eventmodel.EventID = id;
eventmodel.Status = EventStatus.ACCEPTED;
})
.Returns(eventmodel);
var locatorMock = new Mock<IRepositoryLocator>();
locatorMock.Setup(_ => _.GetRepositoryObject(It.IsAny<string>())).Returns(repositoryMock.Object);
var subject = new Consumer(locatorMock.Object);
//Act
var response = subject.EventsAccept(logMsgId);
//Assert
Assert.AreEqual(eventmodel.Status, EventStatus.ACCEPTED);
}
I've got some free time at the moment so am trying to get my head around DI and IoC containers. I've picked unity for no reason other than from what I can tell there are no major differences between the major frameworks that I should be too concerned about starting out. As things get more complex later I realise I may need to change but for now I'm hoping it will do.
So, I'm working with a relatively simple data access scenario and have implemented the following interface, and data access class.
public interface IEventRepository
{
IEnumerable<Event> GetAll();
}
public class EventRepository : IEventRepository
{
public IEnumerable<Event> GetAll()
{
// Data access code here
}
}
Then to use I can do the following.
IUnityContainer container = new UnityContainer();
container.RegisterType(typeof(IEventRepository), typeof(EventRepository));
var eventRepo = container.Resolve<IEventRepository>();
eventRepo.GetAll();
If I needed to change my database provider in 6 months from what I understand I create a new implementation of IEventRepository and update the the type registration, that's fine.
Now, here is where I'm confused. If for example I wanted to implement some caching I could inherit from the appropriate implementation of IEventRepository and override the appropriate methods to implement the necessary caching. However, doing so this way would make it harder to test caching is working correctly using a Moq implementation passed in via DI so in the true spirit of DI I thought it would make sense to create an implementation of IEventRepository, then use DI to request an actual data access implementation of IEventRepository like so.
public class CachedEventRepository : IEventRepository
{
private readonly IEventRepository _eventRepo;
public CachedEventRepository(IEventRepository eventRepo)
{
if (eventRepo is CachedEventRepository)
throw new ArgumentException("Cannot pass a CachedEventRepository to a CachedEventRepository");
_eventRepo = eventRepo;
}
public IEnumerable<Event> GetAll()
{
// Appropriate caching code ultimately calling _eventRepo.GetAll() if needed
}
}
Does this make sense or am I going about this all wrong? What would you suggest? If I am doing it correctly how do I resolve the following situation so that the CachedEventRepository gets the appropriate data access implementation of IEventRepository?
IUnityContainer container = new UnityContainer();
container.RegisterType(typeof(IEventRepository), typeof(EventRepository));
container.RegisterType(typeof(IEventRepository), typeof(CachedEventRepository));
var eventRepo = container.Resolve<IEventRepository>();
eventRepo.GetAll();
Many thanks for your help.
Edit 1
The following is a Moq test I was hoping I would be able to perform, which I don't think would be possible using inheritance and would require DI.
var cacheProvider = new MemoryCaching();
var eventRepo = new Mock<IEventRepository>(MockBehavior.Strict);
eventRepo
.Setup(x => x.GetAll())
.Returns(() =>
{
return new Event[] {
new Event() { Id = 1},
new Event() { Id = 2}
};
});
var cachedEventRepo = new CachedEventRepository(
eventRepo.Object,
cacheProvider);
var data = cachedEventRepo.GetAll();
data = cachedEventRepo.GetAll();
data = cachedEventRepo.GetAll();
Assert.IsTrue(data.Count() > 0);
eventRepo.Verify(x => x.GetAll(), Times.Once());
// This set method should expire the cache so next time get all is requested it should
// load from the database again
cachedEventRepo.SomeSetMethod();
data = cachedEventRepo.GetAll();
data = cachedEventRepo.GetAll();
Assert.IsTrue(data.Count() > 0);
eventRepo.Verify(x => x.GetAll(), Times.Exactly(2));
Ok, after some thinking on the subject and some research on Unity I came up with this.
public class EventRepository : IEventRepository
{
private readonly IDbManager _dbManager;
public EventRepository(IDbManager dbManager)
{
_dbManager = dbManager;
}
public virtual IEnumerable<Event> GetAll()
{
// Data access code
}
}
public class CachedEventRepository : IEventRepository
{
private readonly ICacheProvider _cacheProvider;
private readonly IEventRepository _eventRepo;
public ICacheProvider CacheProvider
{
get { return _cacheProvider; }
}
public CachedEventRepository(IEventRepository eventRepo, ICacheProvider cacheProvider)
{
if(eventRepo is CachedEventRepository)
throw new ArgumentException("eventRepo cannot be of type CachedEventRepository", "eventRepo");
_cacheProvider = cacheProvider;
_eventRepo = eventRepo;
}
public IEnumerable<Event> GetAll()
{
// Caching logic for this method with a call to _eventRepo.GetAll() if required
}
}
This requires the following unity registration. A resolution request for IEventRepository will return a CachedEventRepository. If I want to remove caching quickly I simply remove that CachedEventRepository registration and it will revert back to EventRepository.
IUnityContainer container = new UnityContainer();
container.RegisterType<IDbManager, SqlDbManager>();
container.RegisterType<ICacheProvider, MemoryCaching>();
container.RegisterType<IEventRepository, EventRepository>();
container.RegisterType<IEventRepository, CachedEventRepository>(
new InjectionConstructor(
new ResolvedParameter<EventRepository>(),
new ResolvedParameter<ICacheProvider>())
);
This then allows exactly the tests I'm after.
A simple data access test... Does the SQL work
IUnityContainer container = new UnityContainer();
container.RegisterType<IDbManager, SqlDbManager>();
container.RegisterType<EventRepository>();
var repo = container.Resolve<EventRepository>();
var data = repo.GetAll();
Assert.IsTrue(data.Count() > 0);
A simple cache test... Does the caching system work
var cache = new MemoryCaching();
var getVal = cache.Get<Int32>(
"TestKey",
() => { return 2; },
DateTime.UtcNow.AddMinutes(5));
Assert.AreEqual(2, getVal);
getVal = cache.Get<Int32>(
"TestKey",
() => { throw new Exception("This should not be called as the value should be cached"); },
DateTime.UtcNow.AddMinutes(5));
Assert.AreEqual(2, getVal);
And a test of the two working together... Does the caching on the individual methods work as expected. Does the cache expire when it should, do method argument work correctly to trigger new database requests, etc.
var cacheProvider = new MemoryCaching();
var eventRepo = new Mock<IEventRepository>(MockBehavior.Strict);
eventRepo
.Setup(x => x.GetAll())
.Returns(() =>
{
return new Event[] {
new Event() { Id = 1},
new Event() { Id = 2}
};
});
var cachedEventRepo = new CachedEventRepository(
eventRepo.Object,
cacheProvider);
cachedEventRepo.CacheProvider.Clear();
var data = cachedEventRepo.GetAll();
data = cachedEventRepo.GetAll();
data = cachedEventRepo.GetAll();
Assert.IsTrue(data.Count() > 0);
eventRepo.Verify(x => x.GetAll(), Times.Once());
cachedEventRepo.SomeSetMethodWhichExpiresTheCache();
data = cachedEventRepo.GetAll();
data = cachedEventRepo.GetAll();
Assert.IsTrue(data.Count() > 0);
eventRepo.Verify(x => x.GetAll(), Times.Exactly(2));
What do you think of this? I think it offers good separation and good testability.
I think you're on the right track with a CachedEventRepository, but I would make the EventRepository's GetAll method virtual, and have CachedEventRepository subclass EventRepoistory. Then the subclass can override GetAll, check cache, and if it finds nothing call base.GetAll. It can then cache the results and return the list.
In this way the caching logic is separate from the data access logic, and the subclass is adding caching behavior to your repository.
You can then choose if you want a cached repository, say from a configuration file and configure the Unity container appropriately.
Also, you can have an interface for your caching service as well, so that you can mock that away when unit testing your CachedEventRepository.
Why don't you try to encapsulate all cache logic in one class?
So you'll get something like that:
public interface ICacheManager {}
and
public class CacheManager : ICacheManager {}
So, you could write all you unit-test to ensure that your cache logic is OK. And it will be CacheManagerTest class!
Then you can change you class in this way:
public class EventRepository : IEventRepository
{
private ICacheManager _cacheManager;
public EventRepository(ICacheManager cacheManager)
{
_cacheManager = cacheManager;
}
public IEnumerable<Event> GetAll()
{
// Data access code here
}
}
So, you don't need to test cache logic in your EventRepositoryTest class, cose it's alredy tested.
than you can set up you IoC container to return an instance of ICacheManager with some paramater of Cache policy.
Update
Ok, last try:
public interface IEventRepo
{
IEnumerable<Event> GetAll();
}
public interface ICacheProvider
{
bool IsDataCached();
IEnumerable<Event> GetFromCache();
}
public class CacheProvider : ICacheProvider
{
public bool IsDataCached()
{
//do smth
}
public IEnumerable<Event> GetFromCache()
{
//get smth
}
}
public class EventRepo : IEventRepo
{
private ICacheProvider _cacheProvider;
public EventRepo(ICacheProvider cacheProvider)
{
_cacheProvider = cacheProvider
}
public IEnumerable<Event> GetAll()
{
if (_cacheProvider.IsDataCached())
{
return _cacheProvider.GetFromCache();
}
else
{
//get from repo, save data in cache etc
}
}
}
[TestClass]
public class EventRepoTest
{
[TestMethod]
public void GetsDataFromCacheIfDataIsCachedTest()
{
var cacheProvider = new Mock<ICacheProvider>(MockBehavior.Strict);
cacheProvider
.Setup(x => x.IsDataCached())
.Returns(() =>
{
return true;
});
cacheProvider
.Setup(x => x.GetFromCache())
.Returns(
() => {
return new Event[] {
new Event() { Id = 1},
new Event() { Id = 2}
};
}
);
var eventRepo = new EventRepo(cacheProvider.Object);
var data = eventRepo.GetAll();
cacheProvider.Verify(x => x.GetFromCache(), Times.Once());
}
[TestMethod]
public void GetsDataFromDataBaseIfNotCachedTest()
{
var cacheProvider = new Mock<ICacheProvider>(MockBehavior.Strict);
cacheProvider
.Setup(x => x.IsDataCached())
.Returns(() =>
{
return false;
});
cacheProvider
.Setup(x => x.GetFromCache())
.Returns(
() =>
{
return new Event[] {
new Event() { Id = 1},
new Event() { Id = 2}
};
}
);
var eventRepo = new EventRepo(cacheProvider.Object);
var data = eventRepo.GetAll();
cacheProvider.Verify(x => x.GetFromCache(), Times.Never());
}
}
Not sure in Moq syntax because there is no Moq for WinPhone, but I think it's not a problem.