Skip to content

Instantly share code, notes, and snippets.

@gcollic
Last active August 29, 2015 14:18
Show Gist options
  • Save gcollic/8fb21683c838d8794389 to your computer and use it in GitHub Desktop.
Save gcollic/8fb21683c838d8794389 to your computer and use it in GitHub Desktop.
MVC test helpers
using BoDi;
using Meltingood.Web.App_Start;
using Ninject.MockingKernel.NSubstitute;
using TechTalk.SpecFlow;
namespace Tests
{
[Binding]
public class Config
{
private readonly IObjectContainer _objectContainer;
public Config(IObjectContainer objectContainer)
{
_objectContainer = objectContainer;
MapperConfig.Config();
}
[BeforeScenario]
public void Initialize()
{
var kernel = new NSubstituteMockingKernel();
_objectContainer.RegisterInstanceAs(kernel);
}
}
}
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Web.Mvc;
using NUnit.Framework;
namespace Tests.Helper
{
// Modified version of https://gist.github.com/RhysC/8329873
public static class ControllerTestExtensions
{
public static TAttribute Has<TAttribute>(this Controller controller) where TAttribute : Attribute
{
var attribute = controller.GetType().GetCustomAttributes<TAttribute>().Single();
Assert.NotNull(attribute);
return attribute;
}
public static TAttribute With<TAttribute>(this TAttribute attribute, Func<TAttribute, bool> predicate) where TAttribute : Attribute
{
Assert.True(predicate(attribute));
return attribute;
}
public static MethodInfo Action<TController>(this TController controller, Expression<Func<TController, ActionResult>> expression)
{
var methodCall = expression.Body as MethodCallExpression;
if (methodCall == null) throw new InvalidOperationException("Expression body is expected to be a MethodCallExpression. This is design for Action on Controllers which must be methods.");
return methodCall.Method;
}
public static T Has<T>(this MethodInfo methodInfo) where T : Attribute
{
var att = methodInfo.GetCustomAttributes(typeof(T), true).Single();
Assert.NotNull(att);
return att as T;
}
public static TResult Is<TResult>(this ActionResult actionResult) where TResult : ActionResult
{
Assert.IsAssignableFrom<TResult>(actionResult);
return actionResult as TResult;
}
public static TResult HasViewName<TResult>(this TResult viewResult, string viewName) where TResult : ViewResult
{
Assert.AreEqual(viewName, viewResult.ViewName);
return viewResult;
}
public static TResult HasViewModel<TResult>(this TResult viewResult, object viewModel) where TResult : ViewResult
{
Assert.AreEqual(viewModel, viewResult.Model);
return viewResult;
}
public static TResult WithViewModel<TResult, TModel>(this TResult viewResult, Action<TModel> viewModelAssertions = null) where TResult : ViewResult where TModel : class
{
Assert.IsAssignableFrom<TModel>(viewResult.Model);
if (viewModelAssertions != null)
{
viewModelAssertions.Invoke(viewResult.Model as TModel);
}
return viewResult;
}
public static TResult HasViewBagProperty<TResult>(this TResult viewResult, string viewBagPropertyName, object expectedPropertyValue) where TResult : ViewResult
{
return viewResult.HasViewDataProperty(viewBagPropertyName, expectedPropertyValue);//Viewdata is just the string dict of the view bag
}
public static TResult HasViewDataProperty<TResult>(this TResult viewResult, string viewBagPropertyName, object expectedPropertyValue) where TResult : ViewResult
{
Assert.AreEqual(expectedPropertyValue, viewResult.ViewData[viewBagPropertyName]);
return viewResult;
}
public static TResult HasModelStateErrorMessage<TResult>(this TResult viewResult, string modelStateErrorKey, object expectedErrorMessage) where TResult : ViewResult
{
Assert.AreEqual(expectedErrorMessage, viewResult.ViewData.ModelState.Single(msd => msd.Key == modelStateErrorKey).Value.Errors.Single().ErrorMessage);
return viewResult;
}
public static TResult HasModelStateErrorMessage<TResult>(this TResult viewResult, params string[] modelStateErrorKeys) where TResult : ViewResult
{
foreach (var errorKey in modelStateErrorKeys)
{
Assert.IsTrue(viewResult.ViewData.ModelState.ContainsKey(errorKey));
}
return viewResult;
}
public static TResult HasModelStateError<TResult>(this TResult viewResult) where TResult : ViewResult
{
Assert.IsTrue(viewResult.ViewData.ModelState.Any());
return viewResult;
}
public static TResult HasRedirectUrl<TResult>(this TResult redirectResult, string expectedUrl) where TResult : RedirectResult
{
Assert.AreEqual(expectedUrl, redirectResult.Url);
return redirectResult;
}
public static TResult HasActionName<TResult>(this TResult redirectResult, string expectedName) where TResult : RedirectToRouteResult
{
Assert.AreEqual(expectedName, redirectResult.RouteValues["action"]);
return redirectResult;
}
public static TResult HasRouteValues<TResult>(this TResult redirectResult, object expectedValues) where TResult : RedirectToRouteResult
{
//Assume this is an Anon object
var properties = expectedValues.GetType().GetProperties();
foreach (var propertyInfo in properties)
{
var expectedValue = propertyInfo.GetValue(expectedValues, null);
Assert.AreEqual(expectedValue, redirectResult.RouteValues[propertyInfo.Name]);
}
return redirectResult;
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
namespace Tests.Helper
{
// Modified version of http://blog.brentmckendrick.com/generic-repository-fake-idbset-implementation-update-find-method-identity-key/
public class FakeDbSet<T> : IDbSet<T> where T : class
{
private readonly Func<object[], T, bool> _keyFinder;
private readonly Action<T> _keyGenerator;
private readonly HashSet<T> _data;
private readonly IQueryable _query;
public FakeDbSet(Func<object[], T, bool> keyFinder, Action<T> keyGenerator, IEnumerable<T> startData = null)
{
_keyFinder = keyFinder;
_keyGenerator = keyGenerator;
_data = (startData != null ? new HashSet<T>(startData) : new HashSet<T>());
_query = _data.AsQueryable();
}
public virtual T Find(params object[] keyValues)
{
return this.AsQueryable().SingleOrDefault(x => _keyFinder(keyValues, x));
}
public T Add(T item)
{
_keyGenerator(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 void Detach(T item)
{
_data.Remove(item);
}
Type IQueryable.ElementType
{
get { return _query.ElementType; }
}
Expression IQueryable.Expression
{
get { return _query.Expression; }
}
IQueryProvider IQueryable.Provider
{
get { return _query.Provider; }
}
IEnumerator IEnumerable.GetEnumerator()
{
return _data.GetEnumerator();
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return _data.GetEnumerator();
}
public T Create()
{
return Activator.CreateInstance<T>();
}
public ObservableCollection<T> Local
{
get
{
return new ObservableCollection<T>(_data);
}
}
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T
{
return Activator.CreateInstance<TDerivedEntity>();
}
}
}
using System.Web.Mvc;
using Ninject;
using Ninject.MockingKernel.NSubstitute;
using NSubstitute;
using TechTalk.SpecFlow;
namespace Tests
{
[Binding]
public class AfeatureSteps
{
private readonly NSubstituteMockingKernel _kernel;
private readonly ControllerContext _controllerContext;
public AfeatureSteps(NSubstituteMockingKernel kernel)
{
_kernel = kernel;
_controllerContext = Substitute.For<ControllerContext>();
_kernel.Bind<AFeatureController>().ToSelf().InSingletonScope();
_kernel.Get<AFeatureController>().ControllerContext = _controllerContext;
_kernel.Get<AFeatureController>().Url = Substitute.For<UrlHelper>();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment