MVVM with Unity and Unit Testing architectural design - c#

I'm building a Visual Studio-like application in WPF and I'm having some problems identifying the best architectural design organization of my components. I plan to use Unity as my dependency-injection container and Visual Studio Unit Testing framework and probably moq for mocking library.
I'll first describe the structure of my solution, then my questions:
I have a WPF project that contains:
My Unity container initialization (bootstrapper) on application startup (in App.xaml.cs)
All my application Views (XAML).
Another project called ViewModel this contains:
All my application ViewModels. All my ViewModels inherit from a ViewModelBase which exposes a ILogger property
My initialization logic is as follows:
Application Startup
Unity container creation and registration of types: MainView and MainViewModel
Resolve my MainView and show it.
var window = Container.Resolve<MainView>();
window.Show();
My MainView constructor receives a MainViewModel object in its constructor:
public MainView(MainViewModel _mvm)
My MainViewModel has a Child ViewModel for each of its panels:
public ToolboxViewModel ToolboxVM{get; set;}
public SolutionExplorerViewModel SolutionExplorerVM { get; set; }
public PropertiesViewModel PropertiesVM { get; set; }
public MessagesViewModel MessagesVM { get; set; }
And I'm planning to create a InitializePanels() method that initializes each of the panels.
Now here my questions:
How can my MainViewModel.InitializePanels() initialize all those panels? given the following options:
Option 1: Initialize the ViewModels manually:
ToolboxVM = new ToolboxViewModel();
//Same for the rest of VM...
Cons:
I'm not using the Unity container so my dependencies (e.g. ILogger) are not automatically resolved
Option 2: Use setter injection by annotating my properties:
[Dependency]
public ToolboxViewModel ToolboxVM{get; set;}
//... Same for rest of Panel VM's
Cons:
I've read that Unity Setter dependencies should be avoided since they generate a dependency with Unity in this case
I've also read that you should avoid using Unity for Unit Tests, so how to make this dependency clear in my Unit Tests? Having many dependent properties could be a nightmare to configure.
Option 3: Use Unity Constructor injection to pass ALL my Panel ViewModels to the MainViewModel constructor so they are automatically resolved by Unity container:
public MainViewModel(ToolboxViewModel _tbvm, SolutionExploerViewModel _sevm,....)
Pros:
The dependency would be evident and clear at time of creation, which could help building my ViewModel UnitTests.
Cons:
Having so many constructor parameters could get ugly pretty quickly
Option 4: Registering all my VM types at container buildup. Then passing the UnityContainer instance through constructor injection to my MainViewModel:
public MainViewModel(IUnityContainer _container)
That way I could do something like:
Toolbox = _container.Resolve<ToolboxViewModel>();
SolutionExplorer = _container.Resolve<SolutionExplorerViewModel>();
Properties = _container.Resolve<PropertiesViewModel>();
Messages = _container.Resolve<MessagesViewModel>();
Cons:
If I decide NOT to use Unity for my UnitTests, as many people suggest,then I won't be able to resolve and initialize my Panel ViewModels.
Given that lengthy explanation, what is the best approach so that I can take advantage of a Dependency Injection Container and end up with a Unit-Testable solution??
Thanks in advance,

First things first... As you noticed, your current setup might be problematic when unit testing (complex VM initialization). However, simply following DI principle, depend on abstractions, not on concretions, makes this problem go away immediately. If your view models would implement interfaces and dependencies would be realized through interfaces, any complex initialization becomes irrelevant as in test you'll simply use mocks.
Next, problem with annotated properties is that you create high coupling between your view model and Unity (this is why it is most likely wrong). Ideally, registrations should be handled at single, top level point (which is bootstrapper in your case), so container is not bound in any ways to object it provides. Your options #3 and #4 are most common solutions for this problem, with few notes:
to #3: too many constructor dependencies is usually mitigated by grouping common functionality in facade classes (however 4 is not that many after all). Usually, properly designed code doesn't have this problem. Note that depending on what your MainViewModel does maybe all you need is dependency to list of child view models, not concrete ones.
to #4: you shouldn't use IoC container in unit tests. You simple create your MainViewModel (via ctor) manually and inject mocks by hand.
I'd like to address one more point. Consider what happens when your project grows. Packing all view models into single project might not be good idea. Each view model will have its own (often unrelated to others) dependencies, and all this stuff will have to sit together. This might quickly become difficult to maintain. Instead, think whether you can extract some common functionalities (for example messaging, tools) and have them in separate groups of projects (again, split into M-VM-V projects).
Also, it's much easier to swap views when you have functionality related grouping. If project structure looks like this:
> MyApp.Users
> MyApp.Users.ViewModels
> MyApp.Users.Views
> ...
Trying out different view for user edit window is a matter of recompiling and swapping single assembly (User.Views). With all in one bag approach, you'll have to rebuild much larger part of application, even tho majority of it haven't changed at all.
Edit: keep in mind that changing existing structure of project (even tiny one), is usually a very costly process with minor/none business results. You might not be allowed or simply not be able to afford doing so. Usage-based (DAL, BLL, BO, etc) structure does work, it just gets heavier with time. You can just as well use mixed mode, with core functionalities grouped by their usage and simply adding new functionalities utilizing modular approach.

First off, you'd probably want to use interfaces rather than concrete classes, so that you'll be able to pass you mock objects when unit testing, i.e IToolboxViewModel instead of ToolboxViewModel, etc.
That being said, I would recommend the third option - constructor injection. This makes the most sense, since otherwise you could call var mainVM = new MainViewModel() and end up with a non-functional view model. By doing that, you're also making it very easy to understand what are your view-model's dependencies, which makes it easier to write unit tests.
I would check out this link, as it's relevant to your question.

I agree with Lester's points but wanted to add a few other options and opinions.
Where you are passing the ViewModel to the View through the constructor, this is a bit unconventional as WPF's binding capability allows you to completely decouple the ViewModel from the View by binding to the DataContext object. In the design you've outlined, the View is coupled to a concrete implementation and limits reuse.
While a service facade will simplify option 3, it is not uncommon (as you've outlined) for top-level ViewModels to have a lot of responsibilities. Another pattern you can consider is a controller or factory pattern that assembles the viewmodel. The factory can be be backed by the container to do the work but the container is abstracted away from the caller. A key goal in building container-driven apps is to limit the number of classes that understand how the system is assembled.
Another concern is the amount of responsibilities and object relationships that belong to the top-level viewmodel. If you look at Prism (a good candidate with WPF + Unity) it introduces the concept of "regions" that are populated by modules. A region may represent a toolbar which is populated by mutliple modules. Under such a design, the top-level viewmodel has fewer responsibilities (and dependencies!) and each module contains Unit-testable DI components. Big shift in thinking from the example you've provided.
Regarding option 4, where the container is passed in through the constructor is technically dependency inversion but it's in the form of service location instead of dependency injection. Having gone down this path before I can tell you it's a very slippery slope (more like a cliff): Dependencies are hidden inside classes and your code becomes a web of "just in time" madness -- completely unpredictable, totally untestable.

Related

Unit testing classes that instantiate other classes

I'm trying to write unit tests for a class that instantiates other classes within it, but am struggling with how to instantiate those classes in a testable way. I'm aware of dependency injection, but this is somewhat different as the instantiation doesn't happen in the constructor.
This question really isn't specific to MVVM and C#, but that's what my example will use. Note that I've simplified this and it will not compile as-is - the goal is to show a pattern.
class ItemListViewModel
{
ItemListViewModel(IService service)
{
this.service.ItemAdded += this.OnItemAdded;
}
List<IItemViewModel> Items { get; }
OnItemAdded(IItemModel addedItem)
{
var viewModel = new ItemViewModel(addedItem);
this.Items.Add(viewModel);
}
}
class ItemViewModel : IItemViewModel
{
ItemViewModel(IItem) {}
}
As can be seen above, there is an event from the model layer. The ViewModel listens to that event and, in response, adds a new child ViewModel. This fits with standard Object Oriented programming practices that I'm aware of, as well as the MVVM pattern, and feels like quite a clean implementation to me.
The problem comes when I want to unit test this ViewModel. While I can easily mock out the service using dependency injection, I'm unable to mock out items added through the event. This leads to my primary question: is it OK to write my unit tests depending on the real version of ItemViewModel, rather than a mock?
My gut feel: that isn't OK because I'm now inherently testing more than ItemListViewModel, particularly if ItemListViewModel calls any methods on any of the items internally. I should have ItemListViewModel depend on mock IItemViewModels during testing.
There's a few tactics I've considered for how to do this:
Have ItemListViewModel's owning class listen to the event and add mocked out items. This just moves the problem around, though, as now the owning class can't be fully mocked out.
Pass an ItemViewModel factory into ItemListViewModel and use that instead of new. This would definitely work for mocking as it moves things to be based on dependency injection...but does that mean I need a factory for every class I ever want to mock in my app? This feels wrong, and would be a pain to maintain.
Refactor my model and how it communicates with the ViewModel. Perhaps the eventing pattern I'm using isn't good for testing; though I don't see how I would get around needing to ultimately construct an ItemViewModel somewhere in code that needs to be tested.
Additionally, I've searched online and looked through the book Clean Code, but this really hasn't been covered. Everything talks about dependency injection, which doesn't clearly solve this.
is it OK to write my unit tests depending on the real version of
ItemViewModel, rather than a mock?
Yes!
You should use real implementation as long as tests become slow or very very complicated to setup.
Notice that tests should be isolated, but isolated from other tests not from other dependencies of unit under the test.
Main issue of the testing is that applications using shared state (database, filesystem). Shared state makes our tests dependent on each other (tests for adding and removing items can not be run in parallel). By introducing mocking we eliminate shared state between tests.
Sometimes application being divided into independent domain modules, which "communicate" with each other via abstracted interface. To keep modules independent we will mock communication interface, so module under the test will not depend on implementation details of another domain module.
Mocking literally all dependencies will make maintenance/refactoring changes a nightmare, because every time you going to extract some logic into dedicated class you will be forced to change/rewrite test suit of the unit you are refactoring.
Your scenario is good example, by not mocking creating of ItemViewModel, you will be able to introduce a factory inject it into the class under the test and run already existing test suit to make sure that factory didn't introduce any regressions.
While I can easily mock out the service using dependency injection, I'm unable to mock out items added through the event.
Misko Hevery wrote about this pattern: How to Think About the New Operator
If you mix application logic with graph construction (the new operator) unit-testing becomes impossible for anything but the leaf nodes in your application.
So if we were to look at your problem code:
OnItemAdded(IItemModel addedItem)
{
var viewModel = new ItemViewModel(addedItem);
this.Items.Add(viewModel);
}
then one change we could consider is replacing this direct call to ItemViewModel::new with a more indirect approach
var viewModel = factory.itemViewModel(addedItem);
Where factory provides a capability to create ItemViewModel, and the design allows us to provide substitutes.
ItemListViewModel(IService service, Factory factory)
{
this.service.ItemAdded += this.OnItemAdded;
this.factory = factory;
}
Having done that, you can (when appropriate) use a Factory that provides some simpler implementation of your item view model.
When is this important? One thing to notice is that you are asking about ItemViewModel, but you aren't asking about List. Why is that?
A couple of answers: List is stable; we aren't at all worried that the behavior of List itself is going to change in a way that causes an observable change to the behavior of ItemListViewModel. If the test reports a problem later, there isn't going to be any doubt that we introduced a mistake in our code.
Also, this.List is (presumably) isolated. We don't have to worry that our test results are going to be flaky because some other code is running at the same time. In other words, are test is not vulnerable to problems caused by shared mutable state.
If those properties also hold for ItemViewModel, then adding a bunch of ceremony to your code to create separation between these two implementations isn't actually going to make your design any "better".

WPF, MVVM, Navigation, Keeping Dependency Injection In-Tact

I have a simple WPF application which utilizes the Unity Framework for Dependency Injection. Currently, I am trying to simplify my method for navigation between views in my MVVM pattern implementation; however, many of the examples throughout Stack Overflow do not take into consideration the Dependency Injection caveat.
I have two entirely separate views.
One, Main acts as the main window into which content is loaded (pretty typical; unnecessary content eliminated):
<Window x:Class="Application.UI.Main">
<Grid Background="White">
<ContentControl Content="{Binding aProperty}"/>
</Grid>
</Window>
The constructor receives a ViewModel via constructor injection (again, very simple):
public partial class Main
{
private MainViewModel _mainViewModel;
public Main (MainViewModel mainViewModel)
{
InitializeComponent();
this.DataContext = _mainViewModel = mainViewModel;
}
}
I then have a UserControl, Home, to which I want to "navigate" the main window (i.e. set the ContentControl. It's constructor also receives a ViewModel via constructor injection in the same way Main does. It is equally simple:
public Home(HomeViewModel homeViewModel)
{
InitializeComponent();
// Set Data Context:
this.DataContext = homeViewModel;
}
The main problem, here, is that I want to enable constructor-based injection while maintaining as pure an MVVM implementation as possible.
I am in the View-first camp of MVVM, about which you can find a good discussion in these comments.
I have seen some allusions to the idea of a navigation based service; however, am unsure if that maintains the separation of concerns strived for by MVVM. DataTemplates require View constructors that do not take arguments and I have read criticisms of DataTemplates that argue ViewModels should not participate in the instantiation of Views.
This solution (in my opinion) is just straight wrong as the ViewModel becomes aware of its View and relies on a service for ViewModel instantiaion which makes real Dependency Injection to resolve ViewModel and View dependencies all but impossible. This issue is very evident in the use of RelayCommand in this MSDN article.
Does a navigation service which maintains a global, singleton-like reference to the Main view make the most sense? Is it acceptable for the Main view to expose a method, e.g.:
public void SetContent(UserControl userControl) { //... }
That is then accessed by that service?
This is my articulation of the motivations behind my implementation of the solution provided by another author. I do not provide code as great code examples are provided by the linked article. These are, of course, my opinions but also represent an amalgamation of my research into the topic
No-Container Needed Solution
Rachel Lim wrote a great article, Navigation with MVVM, which describes how to take full advantage of WPF's DataTemplates to solve the challenges presented by MVVM navigation. Lim's approach provides the "best" solution as it greatly reduces the need for any Framework dependencies; however, there really is no "great" way to solve the problem.
The greatest objection to Rachel's approach in general is that the View Model then becomes responsible for - or, "defines" - it's own relationship to the View. For Lim's solution, this is a minor objection for two reasons (and does nothing to further justify other bad architectural decisions, described later):
1.) The DataTemplate relationship is not enforced by anything other than an XAML file, i.e. the View Models are, themselves, never directly aware of their Views nor vice versa, so, even our View's constructor is further simplified, take for example the Home class constructor - now without need for a reference to a View Model:
public Home()
{
InitializeComponent();
}
2.) As the relationship is expressed nowhere else, the association between a particular View and View Model is easy to change.
An application should be able to function (model the domain) sufficiently without a prescribed View. This ideal stems from the effort to best decouple the application's supporting architecture and to foster further application of SOLID programming principles, most specifically dependency injection.
The XAML file - not a third-party dependency container - becomes the pivotal point for resolution of the relationship between the View and the View Model (which, consequently, directly contradicts the OP).
Dependency Injection
An application should be designed to be entirely agnostic of its container and - even better - any implementation-specific information regarding service dependencies. What this allows us to do is to "assign" (inject) services that oblige by a certain contract (interface) to various classes that make up the meat of our applications' functionality.
This leaves us with two criteria for "good design":
Application classes should be able to support a variety of services that perform the same task, as long as they oblige by a described contract.
Application classes should never be aware of - or reference - their container, even if the container is Unity, PRISM, or Galasoft.
The second point is of utmost importance and is a "rule" that is broken, commonly. That "rule breaking" being the inspiration behind the original post.
The response to the navigation problem in many applications is to inject a wrapped dependency injection container which is then used to make calls out of the implementing class to resolve dependencies. The class now knows about the container and, worse, has even greater, more concrete knowledge of what specifics it needs in order to perform its operations (and some might argue more difficult to maintain).
Any knowledge of a dependency resolution container on the part of the View, View Model, or Model is an anti-pattern (you can read more about the justification for that statement elsewhere).
A well written application that relies on dependency injection could function without a dependency injection Framework, i.e. you could resolve the dependencies, manually, from handwritten bootstrapper (though that would require a great deal of careful work).
Lim's solution enables us to "not need" a reference to a container from within the implementation.
What we should be left with are constructors that look like:
// View:
public Home() { //... }
// View Model
public HomeViewModel (SomeModelClass someModel, MaybeAService someService)
If one goal is modularization and reusability, then the above achieves that, well. We could continue to abstract this out further by ensuring those passed-in dependencies are contract fulfillments via interfaces.

Use Singleton for model OR where to inject model into viewmodel?

Normally I'd just use a singleton pattern for the model class Logbook. However, I'm trying to move towards learning about DI and want to inject the model into my viewmodel. In addition, I'm planning on having different child windows that open for various function (choose which logbook entries to display, sort order, add a logbook entry, etc) that may or may not need access to the model. What are the pros and cons of using the singleton pattern vs DI with these constraints? In addition, is DI possible if a lot of my viewmodels need access to this model? Finally, where/how should I instantiate the view, viewmodel, and model to be able to inject?
When you're using dependency injection, the idea is to provide classes with a specific implementation of the dependency it needs, so when you're unit testing, you can provide a mock or stub implementation. This is known as loose coupling.
Singletons, meanwhile, are global state that you have no control over. If your class accesses a singleton, it's tightly coupled to the singleton. How do you mock a singleton? In general, you don't. You're stuck to it, and suddenly you have untestable code. Singletons are generally considered an anti-pattern for exactly this reason. (Aside: there are ways around that, but the basic design problem still exists)
Even worse, if something in your class mutates the state of the singleton, this can have side effects in other tests you're writing and make it very difficult to figure out why Test B passes when run alone, but fails if it's run after Test A.
My rule of thumb is Don't use singletons, ever.
Your specific question sounds a little bit fishy. Your viewmodel shouldn't need a model injected into it. It sounds like you want a class responsible for retrieving or otherwise constructing your model, and then you'd inject an implementation of that class into your viewmodel.

Question on DI and how to solve some problems

I'm a newbie to Dependency Injection. I have never used and never even undestood what it is exatcly all about, but after my last attack on this topic I found out that is a way of uncoupling an object and its dependencies, once they are not responsible for instantiating the concrete versions of its dependencies anymore, as now the container will do it for us and deliver the ready object in our hands.
Now the point is; "when should I use it?", ALWAYS??? Actually, as I'm a newbie and have never even seen a project that uses this pattern I can't undestand how I should apply it to my domain objects!!! It seems to me that I will nevermore instantiate my objects and the container will always do it for me, but then comes some doubts...
1) What about oobjects that part of its dependencies comes from the UI, for example;
public class User(String name, IValidator validator)
Say that I get the user name from the UI, so how will the conatiner know it and still delliver this object for me?
2) Theres other situation I'm facing; if a dependency is now an object that is already instantiated, say... a SINGLETON object, for example . I saw theres settings regarding out the scope of life of the dependency beign injected (im talking about Spring.NET, eg; http request scope)... BUT, request and other web related things are on my presentation layer, so how could I link both my presentation layer and my domain layer without breaking any design rule (as my domain should be totally unaware of where its is being consumed, not to have layer dependency, etc)
Im eager to hear from you all. Thanks very much.
In general, once you go IoC, you tend to want to register EVERYTHING with IoC and have the container spit out fully-hydrated objects. However, you bring up some valid points.
Perhaps a definition of "dependency" is in order; at its broadest, a dependency is simply a set of functionality (interface) that a given class requires a concrete implementation of in order for the class to work correctly. Thus, most non-trivial programs are full of dependencies. To promote ease of maintenance, loose coupling of all dependencies is generally preferred. However, even when loosely coupled, you don't need to automate instantiation of dependencies if those objects require specialized information that you don't want to pollute your IoC registry with. The goal is to loosely couple usage, not necessarily creation.
Concerning point 1, some IoC frameworks don't do well with being given external parameters. However, you can usually register a delegate as a factory method. That delegate may belong to an object like a Controller that is given external information by the UI. Logins are a perfect example: Create an object, say a LoginController, and register it with IoC as your ILoginController. You'll reference that controller on your Login page, it will be injected when the Login page is instantiated, and the login page will pass it the credentials entered. The Controller will then perform authentication, and will have a method GetAuthenticatedUser() that produces a User object. You can register this method with IoC as a Factory for Users, and whenever a User is needed, the factory delegate will either be evaluated, or passed wholesale to the dependent method which will call it when it really needs the User.
On point 2, setting up a single instance of an object is a strength of the IoC pattern. Instead of creating a true singleton, with a private instance constructor, static instance and static constructor to produce an instance, you simply register the class with IoC and tell it to only instantiate it once and use that one instance for all requests. The strength is the flexibility; if you later want there to be more than one instance, you just change the registration. You won't break any design pattern rules either way; the view will always have a Controller injected, whether that Controller is the same for all pages or a new instance per request.
1) this contructor is probably not the right one to use, may be you are injecting the validator in the wrong place/way.
2)Neighter View nor Model and nor Controller should be aware of there is an IoC, it should lie in the background architecture ( where MVC components are actually instantiated )
You should use IoC when you feel the architecture can became complex and has to be mantained by many people. If you are writing an enterprise application, or a UI you think to extend with plugins, you probably need it, if you are writing a command line utility, probably not.
You should use dependency injection whenever you want any of the following benefits:
The ability to replace modules easily
The ability to reuse modules between parts of the application, or different applications
When you want to do parallel development, so that components of a system can be developed in isolation and in parallel because they depend on abstractions
When you want easier maintenance of a system because of loose coupling
When you want testability (a specialisation of replacing modules). This is one of the biggest reasons for using DI
To answer your other questions:
1) You can configure many IoC containers so that certain constructor parameters can be specified, whilst others are resolved by the container. However, you may need to think about refactoring that piece of code, as a UserFactory may be more appropriate which takes the validator dependency, and has a NewUser method which takes a user name and returns a new user (either instantiating it directly or resolving from the container).
2) Each application you build will have a composition root, where your container is configured, and the root object is resolved. Each app will therefore have its own IoC configuration, so there is an expected link between the application type and the configuration settings. Any common abstraction registrations can be placed in configuration code which can be shared amongst all applications.

MVVM pattern and semi-global data

I have developed some MVVM based WPF code and am in need of some minor refactoring but prior to doing that I need to decide the best architecture.
I originally started with an application that could present several similar (but separate) representations of my data. Let's call it RecordsViewModel which had a corresponding RecordsView. As time went on, I introduced a SettingsViewModel which was passed into the constructor of the RecordsViewModel and published visibly (allowing RecordsView to use it). The SettingsViewModel is registered to so that changes are reflected in all of my views.
Now I want to split RecordsView a little because it now contains two distinct views.
The problem I have is:
the new (RecordsMainView and RecordsAlternativeView) both want to see Settings.
unlike the earlier RecordsView which is programmatically instantiated, these new views are instantiated from Xaml (default constructor).
So my options seem to be:
Walk the Tree Model upwards to find a parent with a Settings
Make Settings a DependencyProperty on the controls and make the Xaml join the Property to the instance.
Make SettingsViewModel a Singleton.
Any other, better, options? Which would you consider best?
I would turn your settings logic into a service (ISettingsService) and use service locator or dependency injection to get at that service from whichever view models need it.
Services are great for managing shared state, and service locator / DI makes it very easy for your VMs to get a reference to the service. Storing shared state in a VM is a bit hacky and - as you've found - doesn't really scale. A good rule of thumb might be to ask yourself whether the state in the VM exists only to support the corresponding view, or whether other components will need access to that state. If the latter, move it into a service.

Categories

Resources