C# mock and test helpers with example usage.
//
// TestHelpers.cs
//
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using Moq;
namespace SharedKernel.Data
{
public static class TestHelpers
{
public static DbSet<T> MockDbSet<T>() where T : class
{
return MockDbSet<T>(null);
}
public static DbSet<T> MockDbSet<T>(List<T> inMemoryData) where T : class
{
if (inMemoryData == null)
{
inMemoryData = new List<T>();
}
var mockDbSet = new Mock<DbSet<T>>();
var queryableData = inMemoryData.AsQueryable();
mockDbSet.Setup(m => m.Add(It.IsAny<T>())).Callback<T>(inMemoryData.Add);
//mockDbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryableData.Provider);
mockDbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryableData.Expression);
mockDbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryableData.ElementType);
mockDbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryableData.GetEnumerator());
mockDbSet.Setup(x => x.AsNoTracking()).Returns(mockDbSet.Object);
mockDbSet.Setup(x => x.Include(It.IsAny<string>())).Returns(mockDbSet.Object);
mockDbSet.As<IDbAsyncEnumerable<T>>().Setup(m => m.GetAsyncEnumerator()).Returns(new TestDbAsyncEnumerator<T>(queryableData.GetEnumerator()));
mockDbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(new TestDbAsyncQueryProvider<T>(queryableData.Provider));
return mockDbSet.Object;
}
}
}
//
// TestDbAsyncQueryProvider.cs
//
using System.Collections.Generic;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
namespace SharedKernel.Data
{
internal class TestDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider
{
private readonly IQueryProvider _inner;
internal TestDbAsyncQueryProvider(IQueryProvider inner)
{
_inner = inner;
}
public IQueryable CreateQuery(Expression expression)
{
return new TestDbAsyncEnumerable<TEntity>(expression);
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new TestDbAsyncEnumerable<TElement>(expression);
}
public object Execute(Expression expression)
{
return _inner.Execute(expression);
}
public TResult Execute<TResult>(Expression expression)
{
return _inner.Execute<TResult>(expression);
}
public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute(expression));
}
public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute<TResult>(expression));
}
}
internal class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T>
{
public TestDbAsyncEnumerable(IEnumerable<T> enumerable) : base(enumerable) { }
public TestDbAsyncEnumerable(Expression expression) : base(expression) { }
public IDbAsyncEnumerator<T> GetAsyncEnumerator()
{
return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}
IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
{
return GetAsyncEnumerator();
}
IQueryProvider IQueryable.Provider
{
get
{
return new TestDbAsyncQueryProvider<T>(this);
}
}
}
internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T>
{
private readonly IEnumerator<T> _inner;
public TestDbAsyncEnumerator(IEnumerator<T> inner)
{
_inner = inner;
}
public void Dispose()
{
_inner.Dispose();
}
public Task<bool> MoveNextAsync(CancellationToken cancellationToken)
{
return Task.FromResult(_inner.MoveNext());
}
public T Current
{
get
{
return _inner.Current;
}
}
object IDbAsyncEnumerator.Current
{
get
{
return Current;
}
}
}
}
//
// Example Usage
// ============================================================================
//
// WebSiteOrderingService.cs
//
using System.Collections.Generic;
using MvcSalesApp.Data;
using MvcSalesApp.Domain;
using MvcSalesApp.SharedKernel;
using MvcSalesApp.Web.CustomerFacing.ViewModels;
namespace MvcSalesApp.Services
{
public class WebSiteOrderingService
{
private readonly WebSiteOrderData _siteOrderData;
public WebSiteOrderingService(WebSiteOrderData siteOrderData)
{
_siteOrderData = siteOrderData;
}
public List<ProductLineItemViewModel> GetProductList()
{
var products = _siteOrderData.GetProductsWithCategoryForShopping();
var lineitems = new List<ProductLineItemViewModel>();
products.ForEach(p => lineitems.Add(new ProductLineItemViewModel
{
ProductId = p.ProductId,
CategoryName = p.Category.Name,
Description = p.Description,
Name = p.Name,
Quantity = 0,
MaxQuantity = p.MaxQuantity,
CurrentUnitPrice = p.CurrentPrice
}));
return lineitems;
}
public RevisitedCart ItemSelected(int productId, int quantity,
decimal displayedPrice, string sourceUrl,
string memberCookie, int cartId)
{
if (cartId == 0)
{
return InitializeCart(productId, quantity, displayedPrice, sourceUrl, memberCookie);
}
return AddItemToCart(productId, quantity, displayedPrice, cartId);
}
private RevisitedCart InitializeCart(int productId, int quantity,
decimal displayedPrice, string sourceUrl,
string memberCookie)
{
var cart = NewCart.CreateCartFromProductSelection
(sourceUrl, memberCookie, productId, quantity, displayedPrice);
return _siteOrderData.StoreCartWithInitialProduct(cart);
}
private RevisitedCart AddItemToCart(int productId, int quantity,
decimal displayedPrice, int cartId)
{
var cart = _siteOrderData.RetrieveCart(cartId);
var item = cart.InsertNewCartItem(productId, quantity, displayedPrice);
_siteOrderData.StoreNewCartItem(item);
return cart;
}
public RevisitedCart RetrieveCart(string cartCookie)
{
if (CookieUtilities.IsCartCookie(cartCookie))
{
return _siteOrderData.RetrieveCart(cartCookie);
}
return null;
}
}
}
//
// WebSiteOrderingServiceTests.cs
//
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using ShoppingCart.Data;
using ShoppingCart.Domain;
using SharedKernel.Data;
namespace ShoppingCart.Services.Tests
{
[TestClass]
public class WebSiteOrderingServiceTests
{
private string theUri = "http://www.thedatafarm.com";
[TestMethod]
public void InitializeCartReturnsRevisitedCart()
{
var scContext = new ShoppingCartContext {Carts = TestHelpers.MockDbSet<NewCart>()};
var service = new WebSiteOrderingService(new WebSiteOrderData(scContext, new ReferenceContext()));
Assert.IsInstanceOfType(service.ItemSelected(1, 1, 9.99m, theUri, null, 0), typeof (RevisitedCart));
}
[TestMethod]
public void InitializeCartWithUnknownCustomerStoresZeroInCustomerId()
{
var newCartsInMemory = new List<NewCart>();
var scContext = new ShoppingCartContext {Carts = TestHelpers.MockDbSet(newCartsInMemory)};
var service = new WebSiteOrderingService(new WebSiteOrderData(scContext, new ReferenceContext()));
service.ItemSelected(1, 1, 9.99m, theUri, null, 0);
Assert.AreEqual(0, newCartsInMemory.FirstOrDefault().CustomerId);
}
[TestMethod]
public void InitializeCartWithKnownCustomerStoresValueInCustomerId()
{
var newCartsInMemory = new List<NewCart>();
var mockCustomer = new Mock<Customer>();
mockCustomer.SetupGet(c => c.CustomerCookie).Returns("CustomerCookieABCDE");
mockCustomer.SetupGet(c => c.CustomerId).Returns(1);
var customersInMemory = new List<Customer> {mockCustomer.Object};
var scContext = new ShoppingCartContext {Carts = TestHelpers.MockDbSet(newCartsInMemory)};
var refcontext = new ReferenceContext {Customers = TestHelpers.MockDbSet(customersInMemory)};
var service = new WebSiteOrderingService(new WebSiteOrderData(scContext, refcontext));
service.ItemSelected(1, 1, 9.99m, theUri, "CustomerCookieABCDE", 0);
Assert.AreNotEqual(0, newCartsInMemory.FirstOrDefault().CustomerId);
}
}
}