I am trying to unit test my WinForms application with MVP Passive View implemented. I have created Mock Views and Mock Models so that I can test my Presenters with some data I have set. However, I have run into a problem.
In the constructor of my Presenter, I create my Model. I have thought about eliminating this practice by implementing the Factory Pattern to create my Model without the Presenter knowing anything about the concrete implementation of the Model.
In my unit test, I am trying to test a method from my Presenter(InitializeAssessments) that uses its Model. I want to Presenter to use the Mocked Model there so that there is no connection to a database required and the Presenter just gets the data I set in the Mocked Model. However, since the Presenter creates the 'real' Model, the data is different and my test fails.
Do you think I should implement the Factory Pattern or is there a simple way to fix my issue in the unit testing itsself? Will the Factory Pattern solve my issue?
EDIT: For now I am thinking about creating the Model when I construct the Presenter in the View with homeScreenPresenter = new HomeScreenPresenter(this, new HomeScreenModel()); . So that I only have to reference the IModel in the Presenter itsself, making it easier to test.
Presenter constructor
public HomeScreenPresenter(IHomeScreenView view)
{
_model = new AssessmentsModel();
_view = view;
_view.InitializingAssessments += InitializeAssessments;
_view.CreatingNewAssessment += CreateNewAssessment;
_view.AddingNewStandard += AddNewStandard;
_view.OpeningAssessment += OpenAssessment;
}
Testclass
[TestClass()]
public class HomeScreenPresenterTests
{
MockHomeScreenView view;
MockAssessmentsModel model;
HomeScreenPresenter presenter;
[TestInitialize()]
public void TestInitialize()
{
view = new MockHomeScreenView();
model = new MockAssessmentsModel();
presenter = new HomeScreenPresenter(view);
}
[TestMethod()]
public void HomeScreenPresenterTest()
{
Assert.AreEqual(typeof(MockHomeScreenView), view.GetType());
Assert.AreEqual(typeof(MockAssessmentsModel), model.GetType());
Assert.AreEqual(typeof(HomeScreenPresenter), presenter.GetType());
}
[TestMethod()]
public void InitializeAssessmentsTest()
{
model.TestList = new List<string>
{
"assessment1",
"assessment1",
"assessment2"
};
var expectedList = new List<string>
{
"assessment1",
"assessment2"
};
presenter.InitializeAssessments(this, EventArgs.Empty);
Assert.AreEqual(expectedList, view.ExistingAssessments);
}
I'm creating a WPF MVVM application using Simple Injector as DI container. Now I'm having some issues when I'm trying to resolve a view from Simple Injector, because I'm in need of passing a parameter into my constructor at construction time (not when registering the view to the container, thus this is not applicable: Simple Injector pass values into constructor).
What I'm after is something like this:
var item = container.GetInstance<MyType>(myParameter);
I've read several places that this is not possible in Simple Injector because it should not be done (including here: https://simpleinjector.codeplex.com/discussions/397080).
Is this true, and if so, how could I do this instead?
Background information
I have a collection of multiple view models and models which are looked up by a specific key, and the parameter I want to pass into the view is the key for the view model to use. I've found this necessary because the view models and the models are used in multiple locations of the application, and need to stay in sync / be the same instances if they have the same key. I don't think I'm able to use lifetime scope to solve this, and there is no way I know the keys when I'm registering to the container. I've also understood that the ViewModelLocator approach might be the ServiceLocator (anti-?)pattern, however, currently it is the best I've got.
My constructor currently looks like this, and I want the IViewModelLocator to be resolved, while I pass in the key:
public FillPropertiesView(IViewModelLocator vml, object key)
{
// .. Removed code
// Assign the view model
var viewModel = vml.GetViewModel<FillPropertiesViewModel>(key);
DataContext = viewModel;
}
The IViewModelLocator looks like the following (and a similar interface exists for models).
public interface IViewModelLocator
{
// Gets the view model associated with a key, or a default
// view model if no key is supplied
T GetViewModel<T>(object key = null) where T : class, IViewModel;
}
Now I have the following questions:
What is the best way to be able to resolve the view with the view model key?
Do I have to do some refactoring to enable this?
Am I missing out on some of the power of the DI container since I have created my own dictionary based ViewModelLocator?
Extended information
I have shown the ViewModelLocator above, and the reason I'm using this is to keep blendability (basically it just provides me with design time data when opened in Blend). The runtime view model could have been the same for every instance of the view (not dependent on the key), if I did not have to have different windows opened at the same time (see next paragraph). The issue described above, however, is the same when the ViewModel is fetching a model, and the ModelLocator needs a key to fetch an existing model if it exists.
This is part of a VSTO application targeting PowerPoint (which affects some parts of the design). When an object on screen is selected, a task panel is opened (this is basically the FillPropertiesView explained above). The object that is selected has a key that is supplied to the view, in order for the view to extract the correct view model from the ViewModelLocator. The view model will then get a reference to a model by using a IModelLocator (similar to the IViewModelLocator) and the same key. At the same time, a controller will fetch the model from the ModelLocator by using the same key. The controller listens to change events from the model and updates the objects on screen. The same process is replicated whenever a new object is selected, and at the same time multiple windows could be open that interacts with the same or different objects simultaneously (that is, with multiple task panes all with unique view models).
Up until now I have resolved the view with a default, parameterless constructor, and then injected the view model with a method call afterwards:
// Sets the view model on a view
public void SetViewModel(IViewModelLocator vml, object key)
{
// Assign the view model
_viewModel = vml.GetViewModel<FillPropertiesViewModel>(key);
DataContext = _viewModel;
}
I never had to register the view with the container, but resolved the concrete type like this:
string key = "testkey" // read from the selected object
var view = container.GetInstance<FillPropertiesView>();
var vml = container.GetInstance<IViewModelLocator>();
view.SetViewModel(vml, key);
This issue surfaced when I tried to refactor this so that I did not have to call the SetViewModel() method every and manually resolve the view models etc. It got very messy when I also had to do this manual initiation within the view model to initiate the model in the same way.
ViewModelLocator
The ViewModelLocator is currently working as a wrapper around the DI container, i.e. the view models are registered in Simple Injector.
The registrations are like the following (in a class called CompositionHost):
container.RegisterSingle<IViewModelLocator, ViewModelLocator>();
container.RegisterSingle<IModelLocator, ModelLocator>();
The implementation looks like this:
// Base implementation used by ViewModelLocator and ModelLocator
public class ServiceLocator<TService> where TService : class
{
private readonly Dictionary<CombinedTypeKey, TService> _instances =
new Dictionary<CombinedTypeKey, TService>();
// Gets a service instance based on the type and a key.
// The key makes it possible to have multiple versions of the same service.
public T GetInstance<T>(object key = null) where T : class, TService
{
var combinedKey = new CombinedTypeKey(typeof(T), key);
// Check if we already have an instance
if (_instances.ContainsKey(combinedKey))
{
return _instances[combinedKey] as T;
}
// Create a new instance
// CompositionHost is a static reference to the DI container (and
// should perhaps be injected, however, that is not the main issue here)
var instance = CompositionHost.GetInstance<T>();
_instances.Add(combinedKey, instance);
return instance;
}
// A combined key to ease dictionary operations
private struct CombinedTypeKey
{
private readonly object _key;
private readonly Type _type;
public CombinedTypeKey(Type type, object key)
{
_type = type;
_key = key;
}
// Equals and GetHashCode() are overridden
}
}
public class ViewModelLocator : IViewModelLocator
{
private readonly ServiceLocator<IViewModel> _viewModelLocator;
public ViewModelLocator(ServiceLocator<IViewModel> locator)
{
_viewModelLocator = locator;
// Dummy code that registers design time data is removed
}
// IViewModel is just an empty interface implemented by the view models
public T GetViewModel<T>(object key = null) where T : class, IViewModel
{
return _viewModelLocator.GetInstance<T>(key);
}
}
Injecting a service locator into your classes is (almost) never the way to go, because this disallows compile time checking of dependencies and runtime dependency analysis. For that reason I can also advice to register ALL your root types (such as your views) since otherwise Simple Injector is left in the dark and is not able to advice you about any possible misconfigurations that you might have.
Since you have View + ViewModel pairs that are always cached together, but might depend on Model instance that are reused by multiple View + ViewModel pairs, I suggest the following design.
Define an abstraction for views and view models:
public interface IView<TModel>
{
IViewModel<TModel> ViewModel { get; }
}
public interface IViewModel<TModel>
{
TModel Model { get; set; }
}
Define an abstraction for retrieving/caching view by key.
public interface IViewProvider<TView, TModel> where TView : IView<TModel>
{
TView GetViewByKey(object key);
}
With these abstractions your view can look as follows:
public class FillPropertiesView : IView<FillPropertiesModel>
{
public FillPropertiesView(FillPropertiesViewModel viewModel)
{
this.ViewModel = viewModel;
}
public IViewModel<FillPropertiesModel> ViewModel { get; private set; }
}
And your controllers can depend upon the IViewProvider<TView, TModel> abstraction so they can reload the view when a new key is coming in:
public class FillPropertiesController : Controller
{
IViewProvider<FillPropertiesView, FillPropertiesModel> viewProvider;
FillPropertiesView view;
public FillPropertiesController(
IViewProvider<FillPropertiesView, FillPropertiesModel> provider) {
this.viewProvider = provider;
}
public void Reinitialize(object key) {
this.view = this.viewProvider.GetViewByKey(key);
}
}
The implementation for IViewProvider<TView, TModel> could look like this:
public class ViewProvider<TView, TModel> : IViewProvider<TView, TModel>
where TView : class, IView<TModel> {
Dictionary<object, TView> views = new Dictionary<object, TView>();
Container container;
IModelProvider<TModel> modelProvider;
public ViewProvider(Container container,
IModelProvider<TModel> modelProvider) {
this.container = container;
this.modelProvider = modelProvider;
}
public TView GetViewByKey(object key) {
TView view;
if (!this.views.TryGetValue(key, out view)) {
this.views[key] = view = this.CreateView(key);
}
return view;
}
private TView CreateView(object key) {
TView view = this.container.GetInstance<TView>();
view.ViewModel.Model = this.modelProvider.GetModelByKey(key);
return view;
}
}
This implementation depends on a (previously undefined) IModelProvider<TModel> abstraction. This is basically your old ModelLocator, but by using a generic type you can make the implementation much easier, because we can have one instance of this type per TModel (the same holds for ViewProvider), which saves you from having to do things with storing elements with the { Type + key } combination.
You can register this all as follows:
Assembly asm = Assembly.GetExecutingAssembly();
container.RegisterManyForOpenGeneric(typeof(IView<>), asm);
container.RegisterManyForOpenGeneric(typeof(IViewModel<>), asm);
container.RegisterOpenGeneric(typeof(IViewProvider<,>),
typeof(ViewProvider<,>), Lifestyle.Singleton);
container.RegisterOpenGeneric(typeof(IModelProvider<>),
typeof(ModelProvider<>), Lifestyle.Singleton);
var controllers =
from type in asm.GetTypes()
where type.IsSubClassOf(typeof(Controller))
where !type.IsAbstract
select type;
controllers.ToList().ForEach(t => container.Register(t));
container.Verify();
With RegisterManyForOpenGeneric you let Simple Injector search the supplied assemblies to look for implementations of the given open generic abstraction and Simple Injector will batch-register them for you. With RegisterOpenGeneric you specify an open-generic abstraction and tell Simple Injector which implementation to use when a close-generic version of that abstraction is requested. The last line searches through your application to look for all controller types and registers them in the system.
I'm working on an MVP based GUI architecture for a WinForms application and would like to use Autofac to keep track of the different parts. I keep running into circular component dependencies and would appreciate a gentle push in the right direction.
The architecture is based on this post where the View is as passive as i gets. The View holds no reference to the Presenter. The View is passed to the Presenter on construction. So in the non-DI world you would start your program with:
var MainView = new MainView();
var mainPresenter = new MainPresenter(mainView, new DataRepository());
Application.Run(mainView);
Ok, so the Presenter needs to know about the View instance to do its job. How can I express that in the registration code? This is what I've tried:
builder.RegisterType<MainPresenter>().PropertiesAutowired().SingleInstance();
builder.RegisterType<MainView>().As<IMainView>().PropertiesAutowired().SingleInstance();
And then in Program.cs:
var mainPresenter = Container.Resolve<MainPresenter>();
Application.Run(Container.Resolve<IMainView>() as MainView);
But this way I need to remember to create the Presenter instance. However I would like to express in the registration that if I request a IMainView instance the MainPresenter should be kicked into action. But how....
Any hints, mockery or derisive laughter are welcome
I think you should be able to solve it this way: Register the presenter and view without property injection since you say the view needs no reference to the presenter, and constructor injection is considered best practice in Autofac:
builder.RegisterType<MainPresenter>().SingleInstance();
builder.RegisterType<MainView>().As<IMainView>();
Inject the view into the presenter through constructor and publish it as a readonly property:
public class MainPresenter
{
// Private variables
private readonly IMainView _view;
// Constructor
public MainPresenter(IMainView view)
{
_view = view;
}
// Properties
public IMainView View
{
get { return _view; }
}
}
Then you fire up the application through a single resolve:
var mainPresenter = Container.Resolve<MainPresenter>();
Application.Run(mainPresenter.View as Form);
Finally, if you find later on that you need a reference from the view to the presenter, I think you would have to use property-injection on the view to avoid circular reference exceptions. Then you can register the view like this:
builder.RegisterType<MainView>().As<IMainView>().PropertiesAutowired(PropertyWiringFlags.AllowCircularDependencies);
and supply the view with a read/write property that will be set by Autofac
public MainPresenter Presenter { get; set; }
Let me have two very basic objects like:
public class View
{
public View(Controller controller)
{
// Use the model exposed by the controller here
}
}
public class Controller
{
private readonly IView view;
public Controller()
{
this.view = new View(this);
}
public Controller(View v)
{
this.view = v;
}
}
Later I decide to inject View object into the Controller via DI but there I have a cyclic dependency (i.e. I can't use var ctrl = new Controller(new View(ctrl));). How would you go about injectin the dependency in this case?
The most common solution is to use a dependency property to solve circular dependencies. i.e. create a new property in one of the classes and let the IoC container assign it.
If you are using Unity you should add [Dependency] to that property.
A sidenote: A View should not have a dependency to a controller. It should not be aware of it at all.
Update in reply to comment
You can't. That's the problem with circular dependencies. The only other solution is to use composition. That is to break out the common functionality into a separate class and include it in both the controller and the view.
I actually found a nice solution using Ninject.
public class Controller
{
private readonly View view;
public Controller(ViewModule viewModule)
{
using (IKernel kernel = new StandardKernel(viewModule))
{
this.view = kernel.Get<View>(new ConstructorArgument("controller", this);
}
}
}
Where the ViewModule is a pre-configured Ninject module to resolve the particular view dependency (GUI, CLI, etc.) Minor problem here is that, I'm now dependent on the particular DI framework.
You can't do that at all with constructor-injection
If you change the constructor of the controller to
public Controller(IView view)
in which order would you create the two objects?
View needs the controller Instance and the controller needs the view.
However, you can make the IView Property of the controller public, and set the Property after creation (Some DI-Containers can do this for you automatically when you set the correct attribute).
i am familier with mvc,mvp or mvvm patter. so i was searching google for implementing good design patter for win form apps. i found lots of article.few guys said mvc is good and few guys said mvp is perfect for win apps. i found a very small code which implement mvp in win apps. i go through the code and found that developer has to write lot of extra code to bind treeview or any control.
the code as follows
public interface IYourView
{
void BindTree(Model model);
}
public class YourView : System.Windows.Forms, IYourView
{
private Presenter presenter;
public YourView()
{
presenter = new YourPresenter(this);
}
public override OnLoad()
{
presenter.OnLoad();
}
public void BindTree(Model model)
{
// Binding logic goes here....
}
}
public class YourPresenter
{
private IYourView view;
public YourPresenter(IYourView view)
{
this.view = view;
}
public void OnLoad()
{
// Get data from service.... or whatever soruce
Model model = service.GetData(...);
view.BindTree(model);
}
}
please someone go through the code and help me to understand the flow because how code should be written in mvp patter that i dont know. thanks.
This code is already using the MVP pattern.
It declares an interface IYourView and a concrete class YourView that implements System.Windows.Form and this new interface. Essentially what that is doing is creating a new form with the added requirement that it also implements the BindTree() method defined in IYourView.
The YourView class (form) then has a dependency of YourPresenter in order to hook up the OnLoad event with the presenter, although I'd do it where the presenter subscribes to the form's OnLoad event instead.
The presenter YourPresenter takes as a dependency an instance of YourView and it can then use that instance in the rest of its logic.
Now, to use that you would follow a process similar to this:
Create a new instance of YourView (which then in turn creates the presenter)
Implement logic in the presenter (ie- create GetModel()) to create the Model that you want to bind to the tree
Call view.BindTree(model) in the presenter where model is what you just created in the previous step
So, create an instance of your view:
IYourView newView = new YourView();
Then in your presenter class:
Model model = GetModel();
newView.BindTree(model);