3

In my unit tests, I use things like AssemblyInitialize, ClassInitialize and TestInitialize to configure my tests. In AssemblyInitialize I initialize some singleton factories for creating services, a unit of work and repositories (all trough Unity/Dependency Injection). In my TestInitialize I clear the state they have to make sure each test can run independently.

Trough Stackoverflow I came around the following articles: Writing Testable Code and How to Think About the “new” Operator with Respect to Unit Testing. I have to say they changed how I think about some code I've written but my mind is still buzzing.

For example, take the following code:

public class MyPresenter : BasePresenter<IMyView>
{
    public MyPresenter(IMyView view) 
        : base(view)
    {
    }

    public void PrepareView()
    {
        using (IMyService service = ServiceFactory.Instance.CreateService<IMyService>())
        {
            View.Data = service.GetData();
        }
    }
}

Which is used in an aspx page like this:

Presenter = new MyPresenter(this);
if (!IsPostback)
{
    presenter.PrepareView();
}

How should I change this type of kind with the previous articles in mind? Should I pass a service instance to the PrepareView method? But then my ASPX page has to know about services and factories and stuff and dispose of the service after it's used.

What should I do with my Singleton factory? Make it a property of the class and inject it trough Unity?

Wouter de Kort
  • 39,090
  • 12
  • 84
  • 103

2 Answers2

3

I found this kind of resolving dependencies inelegant, Take a look at the way Ninject wire the dependencies or inject them.

You can see the difference, Service Locator is an antipattern, reading this blog also makes more clear the essential purpose and practices for dependency injection in .NET

Jahan Zinedine
  • 14,616
  • 5
  • 46
  • 70
-3

I see only two options:

  1. Inject a service dependency directly (but you mentioned that do not like resolving a service on the ASPX level)
  2. Pass in the presenter abstracted DI Container and then resolve a dependency in the Presenter (but you mentioned that do not like this way as well since API would be not clear)

I would prefer second option so each presenter is aware of which dependencies it need, since you are using DI Container (Unity) why not get rid of singleton factory and just register all factories in Unity so you would be able accessing it where you need it and unit test a code without any headaches as well (since less singletones). So just pass DI container in the each presenter (considering you noted that do not want keeping all this in ASPX page) as the second parameter and then resolve all required services for a specific presenter:

class Presenter
{
    public Presenter(IView, IDiContainerAbstraction container)
    ...
}

Presenter = new MyPresenter(this, unityContainer); 
public void PrepareView()      
{  
    using (IMyService service = this.unityContainer.Resolve<IMyService>())
    {
        View.Data = service.GetData();  
    }
}

So:

  • No singletone dependencies which makes unit testing possible
  • Since DI container abstracted by interface you would be able passign in presenter Mock whilst unit testing
sll
  • 61,540
  • 22
  • 104
  • 156
  • Wouldn't that break the MVP pattern, having data access in the View? – Magnus Dec 30 '11 at 10:52
  • And what if the service would be used by multiple functions? I don't like the idea of getting this kind of code in my ASPX codebehind.. Then my Web Project suddenly has a reference to a WCF library.. Then we're only one step away of developers calling methods directly on a service (Now, we use Architecture validation to make sure everyone uses the layers correctly) – Wouter de Kort Dec 30 '11 at 10:52
  • I believe presenter accessing a data (`presenter.PrepareView()` method doing this) – sll Dec 30 '11 at 10:53
  • @Wouter de Kort : if many methods need a service - inject it through constructor – sll Dec 30 '11 at 10:54
  • @sll and how would my aspx page inject the service AND dispose of it? – Wouter de Kort Dec 30 '11 at 10:54
  • I believe you can override/subscribe to event to handle Page `UnLoad` stage – sll Dec 30 '11 at 10:56
  • @sll Yeah, I know, but my main point is that it adds responsiblities to my view. which makes the view harder to develop, can't be tested and violates my layer architecture – Wouter de Kort Dec 30 '11 at 10:57
  • it's up to you, then access DI container inside a Presenter. Updated answer. basically we are doing the same in our project (MVVM) - injecting Di Container abstarcted by an interface in the each ViewModel and ViewModel is in chanrge of resolving dependencies – sll Dec 30 '11 at 10:58
  • This would still make the dependencies unclear. If you pass in an empty unityContainer you would get an error. The API is lying! – Wouter de Kort Dec 30 '11 at 11:11
  • You have two ways: 1) inject a dependency directly (but you do not like resolving a service on ASPX level), 2) resolve a dependency in the Presenter, so you do not like both options. Any other possibilities to do this? – sll Dec 30 '11 at 11:15
  • Not that I can think of.. so that's where my question comes from – Wouter de Kort Dec 30 '11 at 11:36
  • I believe there is no magic so you would ends up with any of these solutions, anyway I'm very interested to see other possibilities (except attribute-driven dependency injection) – sll Dec 30 '11 at 11:52
  • Downvoted. You replaced one SL with another. Your code still has hidden dependencies, and is technicly no different from the OP's code. Hidden dependencies = evil. – Frederik Prijck Jan 07 '14 at 14:08