English 中文(简体)
how to mock container.Resolve<Type>()
原标题:

i have a something like this

public class HomeController
{
   public ActionResult Index()
   {
      var x = Container.Resolve<IOrganisationService>();
   }
}

when unit testing i get a null reference exception when the container tries to resolve
anybody knows how do to mock Container.Resolve() ?

最佳回答

I did it, it s like this:

//code inside the setup method
 var c = new Moq.Mock<IWindsorContainer>();
 var l = new Moq.Mock<ILookupService>();
 l.Setup(o => o.GetItems(It.IsAny<String>())).Returns(new List<LookupItem>());
 c.Setup(o => o.Resolve<ILookupService>()).Returns(l.Object);
 LocatorConfigurator.SetContainer(c.Object);
问题回答

You can t, because the Resolve method in question is a static method. This is one of the many reasons static types are considered evil when it comes to unit testing (and hence for general composability of code).

You seem to be applying an (anti)pattern known as Service Locator, and you are currently experiencing one of the many problems associated with it.

A better solution would be to use Constructor Injection like this:

public class HomeController
{
   private readonly IOrganisationService organisationService;

   public HomeController(IOrganisationService organisationService)
   {
       if (organisationService == null)
       {
           throw new ArgumentNullException("organisationService");
       }

       this.organisationService = organisationService;
   }

   public ActionResult Index()
   {
      var x = this.organisationService;
      // return result...
   }
}

You can now let your DI Container of choice resolve the HomeController instance from the outside. This is a much more flexible solution.

The question is, why are you resolving it in that fashion? If you instead have the dependency injected, then you can easily mock:

public class HomeController
{
    private readonly IOrganisationService organisationService;

    public HomeController(IOrganisationService organisationService)
    {
        this.organisationService = organisationService;
    }

   public ActionResult Index()
   {
      var x = this.organisationService;
   }
}

Some containers (Windsor for example) have a container which inherits from an interface. If you use this then it is implicitly mockable. If you have created a static method that you can call resolve on, then as stated above it cannot be mocked isn t advisable. If your container doesn t inherit from an interface (or the service locator pattern you are using) relies on a static method then change the implementation so it s instance based and therefore mockable.

However, I agree with the posts above. You shouldn t really need to reference your container from within your code. This couples your application to a container which is of the things you are trying to avoid by using a container.





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签