模拟Autofac.IComponentContext与单元测试c#

时间:2015-04-23 08:49:09

标签: c# unit-testing autofac nsubstitute

我正在尝试使用NSubstitute模拟IComponentContext,如下所示:

[TestClass()]
public class SyncRepositoryFactoryTests
{
    private IComponentContext _container;
    private SyncRepositoryFactory _factory;

    [TestInitialize]
    public void Initialize()
    {
        _container = Substitute.For<IComponentContext>();
        _factory = new SyncRepositoryFactory(_container);
    }

    [TestMethod]
    public void Get_SyncRepositoryOfITestEntity_Success()
    {
        var repository = Substitute.For<IRepository<TestEntity>>();
        _container.Resolve<IRepository<TestEntity>>().Returns(repository);

        var result = _factory.Get<ITestEntity>();

        Assert.IsNotNull(result);
        Assert.IsTrue(result is ISyncRepository<ITestEntity>);
    }

    public interface ITestEntity 
    {
    }

    public class TestEntity : ITestEntity
    {
    }
}

但我得到一个例外:

    ComponentNotRegisteredException: The requested service 
        'Hvb.eMarketAdvisor.Repository.SharePoint.IRepository`1[[Hvb.eMarketAdvisor.
        Repository.SharePoint.Tests.Units.SyncRepositoryFactoryTests+TestEntity, 
        Hvb.eMarketAdvisor.Repository.SharePoint.Tests.Units, 
    Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' has not been registered. 

    To avoid this exception, either register a component to provide the service,
    check for service registration using IsRegistered(), or use the ResolveOptional()
    method to resolve an optional dependency.

当我尝试创建模拟时,为什么IComponentContext尝试解决依赖?

2 个答案:

答案 0 :(得分:2)

因为Resolve<>()是一种扩展方法,所以您只是执行扩展方法,而不是模拟其调用。您需要模拟扩展方法调用的调用。

正如上述评论者所说,如果您正在嘲笑您的DI容器,那么您的设计就会出现问题。

答案 1 :(得分:0)

一个老问题,但是如果有人出于您的原因来寻找如何做的事情,那么从Autofac 4.9.2开始,以下内容应该对您有用。显然,如果您需要更多的逻辑,可以通过替换来实现。

public interface ICalculate
{
    bool ProcessData();
}

public class ReallyCoolCalculate : ICalculate
{
    public bool ProcessData()
    {
        return 2 + (2 * 3) == 8;
    }
}

public void GetCalculateFromAutoFac()
{
    var calculate = new ReallyCoolCalculate();

    var componentContext = Substitute.For<IComponentContext>();
    var componentRegistration = Substitute.For<IComponentRegistration>();
    componentContext.ComponentRegistry.TryGetRegistration(Arg.Any<Service>(), out Arg.Any<IComponentRegistration>()).Returns(true);
    componentContext.ResolveComponent(Arg.Any<IComponentRegistration>(), Arg.Any<IEnumerable<Parameter>>()).Returns(calculate);

    var calculateFromAutoFac = componentContext.Resolve<ICalculate>();

}