Does anyone have an implementation lying around of an auto-mock container using Rhino Mocks and NInject?
OK I built one myself using the Moq integration as a starting point. It is very simple. You need these 3 classes:
public class AutoMockingKernel : StandardKernel
{
private readonly IMockProvider _mockProvider;
public void Reset()
{
Components.Get<ICache>().Clear();
}
protected override bool HandleMissingBinding(Type service)
{
var isSelfBindable = TypeIsSelfBindable(service);
var binding = new Binding(service)
{
ProviderCallback = isSelfBindable
? StandardProvider.GetCreationCallback(service)
: _mockProvider.GetCreationCallback(),
IsImplicit = true
};
if (!isSelfBindable)
binding.ScopeCallback = ctx => null;
AddBinding(binding);
return true;
}
public AutoMockingKernel(IMockProvider mockProvider, INinjectSettings settings, params INinjectModule[] modules)
: base(settings, modules)
{
_mockProvider = mockProvider;
}
public AutoMockingKernel(IMockProvider mockProvider, params INinjectModule[] modules)
: base(modules)
{
_mockProvider = mockProvider;
}
}
internal class RhinoMockProvider : IProvider
{
public Type Type { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="RhinoMockProvider"/> class.
/// </summary>
public RhinoMockProvider(Type type)
{
Type = type;
}
public object Create(IContext context)
{
return MockRepository.GenerateMock(Type, Type.EmptyTypes);
}
}
public class RhinoAutoMockProvider : IMockProvider
{
public Func<IContext, IProvider> GetCreationCallback()
{
return ctx => new RhinoMockProvider(ctx.Request.Service);
}
}
You can then create an auto-mocking kernel in your unit test like this:
[Test]
public void Test()
{
var kernel = new AutoMockingKernel(new RhinoAutoMockProvider());
... etc
}
There is a RhinoMocks integration extension available.
Related
I am trying to grasp the fundamentals of raising/handling a Domain Event in my Solution. I am using Visual Studio 2017, .Net Core 1.1, C#, StructureMap 4.5.1.
The failure in my code came to light in a Unit Test which failed when checking if my Domain Event was being raised correctly.
My Startup.cs class includes the following code:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddSingleton(_config);
services.AddAutoMapper();
services.AddMvc()
.AddControllersAsServices();
return ConfigureIoC(services);
}
public IServiceProvider ConfigureIoC(IServiceCollection services)
{
var container = new Container();
container.Configure(config =>
{
config.Scan(scan =>
{
scan.AssemblyContainingType(typeof(Startup));
scan.Assembly("Shared");
scan.Assembly("TaskScheduling");
scan.Assembly("TaskScheduling_Tests");
scan.WithDefaultConventions();
scan.ConnectImplementationsToTypesClosing(typeof(IHandle<>));
});
//Populate the container using the service collection
config.Populate(services);
});
return container.GetInstance<IServiceProvider>();
}
Where possible I have been following Udi Dahan's approach Domain Events - Salvation
My DomainEvents class implements the following Interface:
using System;
namespace Shared.Interfaces
{
public interface IDomainEvent
{
DateTime DateTimeEventOccurred { get; }
}
}
The DomainEvents class is as follows:
using System;
using System.Collections.Generic;
using Shared.Interfaces;
using StructureMap;
namespace Shared
{
/// <summary>
/// http://udidahan.com/2009/06/14/domain-events-salvation/
/// http://msdn.microsoft.com/en-gb/magazine/ee236415.aspx#id0400046
///
/// This class registers Domain Events and makes sure they get called.
/// </summary>
public static class DomainEvents
{
[ThreadStatic]
private static List<Delegate> actions;
public static IContainer Container { get; set; }
// Registers a callback for the given domain event.
public static void Register<T>(Action<T> callback) where T : IDomainEvent
{
if (actions == null)
{
actions = new List<Delegate>();
}
actions.Add(callback);
}
// Clears callbacks passed to Register on the current thread.
public static void ClearCallbacks()
{
actions = null;
}
// Raises the given domain event.
public static void Raise<T>(T args) where T : IDomainEvent
{
foreach (var handler in Container.GetAllInstances<IHandle<T>>())
{
handler.Handle(args);
}
if (actions != null)
{
foreach (var action in actions)
{
if (action is Action<T>)
{
((Action<T>)action)(args);
}
}
}
}
}
}
I have a Task class which when updated raises a TaskUpdatedEvent. The TaskUpdatedEvent class is as follows:
using Shared.Interfaces;
using System;
namespace TaskScheduling.Model.Events
{
public class TaskUpdatedEvent : IDomainEvent
{
/// <summary>
/// When creating a TaskUpdatedEvent you have to pass in the Task object.
/// </summary>
/// <param name="task"></param>
public TaskUpdatedEvent(ScheduleAggregate.Task task)
: this()
{
TaskUpdated = task;
}
public TaskUpdatedEvent()
{
this.Id = Guid.NewGuid();
DateTimeEventOccurred = DateTime.Now; // IDomainEvent interface requirement.
}
public Guid Id { get; private set; }
public DateTime DateTimeEventOccurred { get; private set; }
public ScheduleAggregate.Task TaskUpdated { get; private set; }
}
}
and the event is raised with the following lines in my Task class:
var taskUpdatedEvent = new TaskUpdatedEvent(this);
DomainEvents.Raise(taskUpdatedEvent);
I only have one Unit Test, so far, to check if this event is being raised. The Unit Test is as follows:
using System;
using NUnit.Framework;
using Shared;
using TaskScheduling.Model.ScheduleAggregate;
using TaskScheduling.Model.Events;
namespace TaskScheduling_Tests
{
[TestFixture]
public class TaskUpdatedEventShould
{
private Task testTask;
private readonly Guid testScheduleId = Guid.NewGuid();
private const int TestLocationId = 567;
private const int TestDeviceId = 123;
private const int TestTaskTypeId = 1;
private readonly DateTime testStartTime = new DateTime(2014, 7, 1, 9, 0, 0);
private readonly DateTime testEndTime = new DateTime(2014, 7, 1, 9, 30, 0);
private readonly DateTimeRange newTaskTimeRange = new DateTimeRange(new DateTime(2014, 6, 9, 10, 0, 0), TimeSpan.FromHours(1));
private const string TestTitle = "Unit Test Title";
[SetUp]
public void SetUp()
{
DomainEvents.ClearCallbacks();
testTask = Task.Create(
testScheduleId,
TestLocationId,
TestDeviceId,
TestTaskTypeId,
testStartTime,
testEndTime,
TestTitle
);
}
[Test]
public void EntityConstructor_IsNot_Null()
{
Assert.IsNotNull(testTask);
}
[Test]
public void RaiseTaskUpdatedEvent()
{
// Arrange
Guid updatedAppointmentId = Guid.Empty;
DomainEvents.Register<TaskUpdatedEvent>(aue =>
{
// This defines happens when the event is raised/
// The 'updatedAppointmentId' is changed from being all zeros to the testTask's id value.
updatedAppointmentId = testTask.Id;
});
// Act
testTask.UpdateTime(newTaskTimeRange);
// Assert
Assert.AreEqual(testTask.Id, updatedAppointmentId);
}
}
}
The failure appears to occur in the DomainEvent class when the Raise method is called. Debugging shows that the event is raised and the arguments are set, however the Container is Null so the foreach loop cannot check for handlers.
I cannot figure out why the Container is Null but I'm sure I must be missing something obvious. Any suggestions welcome.
I followed the instructions in this article to use Ninject for MVC 4 Web API Controller Constructor injection:
http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api/
the problem that i am facing is when i call the api method i get error saying "Type 'CarController' does not have a default constructor".
i have even set break points at NinjectWebCommon.CreateKernel to see if that is being called. And that does get called when application runs.
Am i missing any thing?
by the way, i installed Ninject.Web.Common and Ninject from nuget for doing this. Here is my code:
MVC WEB API Controller:
public class CarController : ApiController
{
private ICarService carService;
public CarController(ICarService carService)
{
this.carService = carService;
}
[AcceptVerbs("GET")]
public CarsResponse GetCars([FromUri] CarsRequest request)
{
return this.carService.GetCars(request);
}
}
in App_Start:
public class NinjectDependencyScope : IDependencyScope
{
IResolutionRoot resolver;
public NinjectDependencyScope(IResolutionRoot resolver)
{
this.resolver = resolver;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.TryGet(serviceType);
}
public System.Collections.Generic.IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.GetAll(serviceType);
}
public void Dispose()
{
IDisposable disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
}
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
my NinjectWebCommon looks like this:
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
public static void Stop()
{
bootstrapper.ShutDown();
}
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICarService>().To<CarService>();
}
}
I was having the same issue. I found the resolution by doing the following. I lost track of the webpage where I found the class NinjectMVCDependencyResolver.
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
// Install our Ninject-based IDependencyResolver into the Web API config
GlobalConfiguration.Configuration.DependencyResolver
= new NinjectDependencyResolver(kernel);
// Install into the MVC dependency resolver
System.Web.Mvc.DependencyResolver.SetResolver(
new NinjectMVCDependencyResolver(kernel));
return kernel;
}
public class NinjectMVCDependencyResolver : NinjectDependencyScope
, System.Web.Mvc.IDependencyResolver
{
private IKernel kernel;
public NinjectMVCDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
I am running into the below error the first time my ViewModel is being instantiated by the SimpleIoC. I believe I have setup the container as it should be, but for some reason, I am still getting the below error. Any ideas or assistance would be very much appreciated.
Microsoft.Practices.ServiceLocation.ActivationException was unhandled by user code
HResult=-2146233088
Message=Type not found in cache: Windows.UI.Xaml.Controls.Frame.
Source=GalaSoft.MvvmLight.Extras
StackTrace:
at GalaSoft.MvvmLight.Ioc.SimpleIoc.DoGetService(Type serviceType, String key) in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 532
at GalaSoft.MvvmLight.Ioc.SimpleIoc.GetService(Type serviceType) in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 768
at GalaSoft.MvvmLight.Ioc.SimpleIoc.MakeInstance[TClass]() in c:\Users\Public\Downloads\CodePlex\MVVMLight\GalaSoft.MvvmLight\GalaSoft.MvvmLight.Extras (NET35)\Ioc\SimpleIoc.cs:line 708
InnerException:
Here are pieces of my code related to this:
ViewModelLocator.cs (Located in my Win8 project)
public class ViewModelLocator
{
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
// Create design time view services and models
//SimpleIoc.Default.Register<IDataService, DesignDataService>();
}
else
{
// Create run time view services and models
//SimpleIoc.Default.Register<IDataService, DataService>();
SimpleIoc.Default.Register<INavigationService, NavigationService>();
SimpleIoc.Default.Register<IParseService, ParseService>();
SimpleIoc.Default.Register<IServiceHandler, ServiceHandler>();
}
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<ActionViewModel>();
}
public MainViewModel MainVM
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public ActionViewModel ActionVM
{
get
{
return ServiceLocator.Current.GetInstance<ActionViewModel>();
}
}
public static void Cleanup()
{
// TODO Clear the ViewModels
}
}
MainViewModel.cs Constructor
public class MainViewModel : ViewModelBase
{
#region Variables
private readonly INavigationService _navigationService;
private readonly IParseService _parseService;
#endregion
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel(INavigationService navigationService, IParseService parseService)
{
if (IsInDesignMode)
{
// Code runs in Blend --> create design time data.
}
else
{
_navigationService = navigationService;
_parseService = parseService;
BuildCommonData();
}
}
I know this is long overdue, but here is the offending code in the implementation of my NavigationService class.
NavigationService class (Before)
public class NavigationService : INavigationService
{
/// <summary>
/// Gets the root frame.
/// </summary>
private Frame RootFrame;
public NavigationService(Frame rootFrame)
{
RootFrame = rootFrame;
}
public event NavigatingCancelEventHandler Navigating;
public void Navigate<T>(object parameter = null)
{
var type = typeof(T);
RootFrame.Navigate(type, parameter);
}
public void Navigate(string type, object parameter = null)
{
RootFrame.Navigate(Type.GetType(type), parameter);
}
public void GoBack()
{
if (RootFrame.CanGoBack)
{
RootFrame.GoBack();
}
}
public void GoForward()
{
if (RootFrame.CanGoForward)
{
RootFrame.GoForward();
}
}
}
I simply took out the constructor, and made the RootFrame private variable a property. Like so:
public class NavigationService : INavigationService
{
/// <summary>
/// Gets the root frame.
/// </summary>
private static Frame RootFrame
{
get { return Window.Current.Content as Frame; }
}
public event NavigatingCancelEventHandler Navigating;
public void Navigate<T>(object parameter = null)
{
var type = typeof(T);
RootFrame.Navigate(type, parameter);
}
public void Navigate(string type, object parameter = null)
{
RootFrame.Navigate(Type.GetType(type), parameter);
}
public void GoBack()
{
if (RootFrame.CanGoBack)
{
RootFrame.GoBack();
}
}
public void GoForward()
{
if (RootFrame.CanGoForward)
{
RootFrame.GoForward();
}
}
}
Simple, I know, but hope it's of some use.
I was getting the same error today in my Xamarin project. The actual error given was "System.Reflection.TargetInvocationException: 'Exception has been thrown by the target of an invocation.'" and then when I look up the InnerException I could see the actual error, which is Type not found in cache.
It was a silly mistake that I was using DataService instead of IDataService for the Constructor Dependency Injection.
public SearchViewModel(DataService dataService, IErrorLoggingService errorLoggingService, IDialogService dialogService, IResourceService resourceService, INavigationService navigationService) {
SearchCommand = new AsyncRelayCommand <SearchFilter>(SearchAsync);
DataService = dataService;
ErrorLoggingService = errorLoggingService;
DialogService = dialogService;
ResourceService = resourceService;
NavigationService = navigationService;
CancelCommand = new RelayCommand(Cancel);
}
And just for your information, this is how I registered my service.
SimpleIoc.Default.Register<IDataService, DataService>();
So the issue was fixed after changing to IDataService. Hope it helps.
A bit of history first. I created a EF Code First Library that contains POCO Objects as my Models, a generic DataProvider that inherits from DbContext, generic Repostory that implements the generic DataProvider, and a generic Service that implements the repository. I have used this library successfully in WPF (MVVM), ASP.Net, Window Forms, and ASP MVC applications.
For this discussion I will reference the Company Model
From the top down, I create a Service class called CompanyService that inherits from a base Service Class. The CompanyService class contains all of the business logic for the Company Model. This class uses the Repository class to perform the CRUD operations. The Repository then encapsulates all the DataProvider class operations.
I have done some research on using EF with WCFDataService, but I can't get my head around how to implement my library with it, particulary when it comes to overriding the CreateDataSource() Method.
It may be that I should just use a WCF Service instead, maybe I'm not understanding the purpose of the WCFDataService.
I have listed partial code for the classes involved:
public class CompanyService : ServiceBase<Company> ,ICompanyService
{
public Company GetCompanyByFolderId(string eFolderId)
{
return (Company)GetModelByFolderId(eFolderId);
}
}
public abstract class ServiceBase<TModel> : IService<TModel> where TModel : class, IModel
{
private IDataProvider _dataProvider;
public IDataProvider DataProvider
{
get
{
if (_dataProvider == null)
{
string connectionStringName = Properties.Settings.Default.DataProvider;
bool enableLazyLoading = true;
_dataProvider = new DataProvider(connectionStringName, enableLazyLoading);
}
return _dataProvider;
}
set
{
_dataProvider = value;
}
}
private IRepository<TModel> _repository;
public IRepository<TModel> Repository
{
get
{
if (_repository == null)
{
_repository = new Repository<TModel>(DataProvider);
}
return _repository;
}
set
{
_repository = value;
}
}
public TModel GetModelByFolderId(String folderId)
{
return GetTable().FirstOrDefault(o => o.EFolderid == folderId);
}
public virtual IQueryable<TModel> GetTable()
{
return Repository.GetTable();
}
}
public class Repository<TModel> : IRepository<TModel> where TModel : class, IModel
{
private IDataProvider _dataProvider;
public Repository(IDataProvider dataProvider)
{
_dataProvider = dataProvider;
}
private IDbSet<TModel> DbSet
{
get
{
return _dataProvider.Set<TModel>();
}
}
public IQueryable<TModel> GetTable()
{
return _dataProvider.GetTable<TModel>();
}
}
public class DataProvider : DbContext, IDataProvider
{
public DataProvider()
{
}
public DataProvider(string connectionStringName, bool enableLazyLoading = true)
: base(connectionStringName)
{
Configuration.LazyLoadingEnabled = enableLazyLoading;
//Configuration.ProxyCreationEnabled = false;
}
public new IDbSet<TModel> Set<TModel>() where TModel : class
{
return base.Set<TModel>();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new CompanyMapping());
base.OnModelCreating(modelBuilder);
}
public IQueryable<TModel> GetTable<TModel>() where TModel : class
{
return Set<TModel>().AsQueryable();
}
}
Then my Test looks something like this:
[TestClass()]
public class CompanyServiceTest
{
[TestMethod()]
public void GetCompanies()
{
CompanyService target = new CompanyService();
IQueryable<Company> companies = target.GetTable();
Assert.IsNotNull(companies);
}
[TestMethod()]
public void GetCompanyByFolderId()
{
CompanyService target = new CompanyService();
Company company = target.GetCompanyByFolderId("0000000000000000000000000172403");
Assert.IsNotNull(company);
}
}
Is it possible to change the default object scope in Ninject 2.2? If so, how is it done?
As far as I can tell you could override AddBinding() on the BindingRoot (StandardKernel or NinjectModule) and modify the ScopeCallback property on the binding object.
public class CustomScopeKernel : StandardKernel
{
public CustomScopeKernel(params INinjectModule[] modules)
: base(modules)
{
}
public CustomScopeKernel(
INinjectSettings settings, params INinjectModule[] modules)
: base(settings, modules)
{
}
public override void AddBinding(IBinding binding)
{
// Set whatever scope you would like to have as the default.
binding.ScopeCallback = StandardScopeCallbacks.Singleton;
base.AddBinding(binding);
}
}
This test should now pass (using xUnit.net)
public class DefaultScopedService { }
[Fact]
public void Should_be_able_to_change_default_scope_by_overriding_add_binding()
{
var kernel = new CustomScopeKernel();
kernel.Bind<DefaultScopedService>().ToSelf();
var binding = kernel.GetBindings(typeof(DefaultScopedService)).First();
binding.ScopeCallback.ShouldBe(StandardScopeCallbacks.Singleton);
}
The CustomScopeKernel will also work with Ninject modules.
public class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<DefaultScopedService>().ToSelf();
}
}
[Fact]
public void Should_be_able_to_change_default_scope_for_modules()
{
var module = new ServiceModule();
var kernel = new CustomScopeKernel(module);
var binding = kernel.GetBindings(typeof(DefaultScopedService)).First();
binding.ScopeCallback.ShouldBe(StandardScopeCallbacks.Singleton);
}