views:

113

answers:

3

I am working on a WPF application, using the MVVM Pattern.

Each ViewModel will need access to a security object, that essentially provides information about the rights the user has. Because this object only needs to be populated once at start up, and because populating it is (at least potentially) expensive, I want to keep it in state for the lifetime of the application.

I can make it a static variable in App, which would make it available to the whole application (at least that's my understanding). This would make my ViewModel implementations very difficult to test, since the App.SecurityObject call would be inline in each ViewModel. I would have to make sure App was available for each test and mock the App.SecurityObject call (I'm not even sure this would work, actually).

We are using StructureMap, so I could create a SecurityObjectProvider and configure a it with a Singleton lifecycle in the container, and simply make it part of every ViewModel constructor. The downside would be that (as I said) the provider would have to be part of every View Model constructor.

There are other, hacky workarounds I can think of, but they would involve creating methods (perhaps in the View Model base class) that would allow injecting the security object after instantiation for testing purpose only. I usually try to avoid this kind "for testing only" code.

It seems like this would be a common problem , but I can't find any SO questions that are completely on point.

+2  A: 

The service locator pattern might help you out. You still implement the functionality as a service, but you have your VMs go through a static class to obtain the service, rather than have it injected:

var securityService = ServiceLocator.Resolve<ISecurityService>();

When running unit tests, you can configure your service locator to return mocks/stubs.

HTH,
Kent

Kent Boogaart
:)) 30 seconds! You win :)!
Anvaka
Interesting. So the service locator itself is container-managed, or utilizes a container in its resolve() method, and I configure it differently for production and for testing?
Phil Sandler
Right. The service locator can be as simple as a wrapper around an IDictionary, or could use a DI container behind the scenes. Doesn't really matter, as long as you can easily configure it via code so unit testing is easy. eg. `ServiceLocator.Register<TFrom, TTo>()` and `ServiceLocator.RegisterInstance<T>(T instance)`
Kent Boogaart
A: 

Hi Phil,

I think I would use some kind of Service Locator to get object. And in tests I would mock it out.

Anvaka
+2  A: 

Security concerns are often best adressed by Thread.CurrentPrincipal. If it's at all possible to fit your security concerns into that model (calling Principal.IsInRole and so on) that is by far the desirable solution.

It's pretty easy to unit test because you just need to set Thread.CurrentPrincipal before invoking the SUT and then make sure you revert it to its original value in the Fixture Teardown phase.

If Thread.CurrentPrincipal doesn't suit your need, I would suggest either an injected dependency or a Decorator that handles security. Security is often a Cross-Cutting Concern, so it is often preferable to handle it as declaratively as possible. In other words, if you can model it by Guards and Assertions, you don't need to actively call it, and you would be able to use a more AOP-like approach (such as a Decorator).

If that's not possible either, you can model it as an Ambient Context. This may look a bit like the Service Locator anti-pattern, but the difference is that it's strongly typed and has a Local Default that ensures that it never throws NullReferenceExceptions or their like because it protects its invariants.

Mark Seemann