我有类似的东西
public class HomeController
{
public ActionResult Index()
{
var x = Container.Resolve<IOrganisationService>();
}
}
当单元测试时,当容器尝试解析时,我得到一个空引用异常
谁知道如何模拟Container.Resolve()?
答案 0 :(得分:7)
你不能,因为有问题的Resolve方法是静态方法。这是静态类型在单元测试中被认为是 evil 的众多原因之一(因此也是代码的一般可组合性)。
您似乎正在应用称为服务定位器的(反)模式,并且您目前遇到了与之相关的许多问题之一。
更好的解决方案是使用构造函数注入,如下所示:
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...
}
}
您现在可以让您选择的DI容器从外部解析HomeController实例。这是一个更灵活的解决方案。
答案 1 :(得分:5)
问题是,为什么要以这种方式解决它?如果您反而注入了依赖项,那么您可以轻松地模拟:
public class HomeController
{
private readonly IOrganisationService organisationService;
public HomeController(IOrganisationService organisationService)
{
this.organisationService = organisationService;
}
public ActionResult Index()
{
var x = this.organisationService;
}
}
答案 2 :(得分:0)
某些容器(例如Windsor)有一个继承自接口的容器。如果你使用它,那么它是隐式可模拟的。如果您已经创建了一个可以调用resolve的静态方法,那么如上所述它不能被模拟是不可取的。如果您的容器没有从接口继承(或者您正在使用的服务定位器模式),则依赖于静态方法,然后更改实现,使其基于实例,因此可以模拟。
但是,我同意上述帖子。您不应该真正需要在代码中引用容器。这会将您的应用程序耦合到一个容器,这是您要使用容器避免的事情。
答案 3 :(得分:-1)
我做到了,就像这样:
//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);