i have a something like thi开发者_如何学JAVAs
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() ?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.
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);
精彩评论