NSubstitute和Autofac - 断言不能按预期工作

时间:2013-10-27 13:42:19

标签: autofac nsubstitute

我有一个Web API项目,它有以下类。该类基本上是注册所有ApiController个实例并设置DependencyResolver

public class DependencyResolverConfig
{
    public static void Register(HttpConfiguration configuration, ContainerBuilder containerBuilder)
    {
        containerBuilder.RegisterApiControllers(Assembly.GetExecutingAssembly());
        var container = containerBuilder.Build();
        var resolver = new AutofacWebApiDependencyResolver(container);
        configuration.DependencyResolver = resolver;
    }
}

为了测试这个类实际上是在设置所有API控制器,我有以下测试

[Test]
public void RegistersApiControllers()
{
    var config = new HttpConfiguration();
    var containerBuilder = Substitute.For<ContainerBuilder>();
    containerBuilder.RegisterApiControllers(Arg.Any<Assembly>());

    DependencyResolverConfig.Register(config, containerBuilder);
    containerBuilder.Received(2).RegisterApiControllers();
}

当我运行此测试时,我会从NSubstitute

获得以下异常
NSubstitute.Exceptions.ReceivedCallsException : Expected to receive exactly 2 calls matching:
    RegisterCallback(Action<IComponentRegistry>)
Actually received no matching calls.
Received 2 non-matching calls (non-matching arguments indicated with '*' characters):
    RegisterCallback(*Action<IComponentRegistry>*)
    RegisterCallback(*Action<IComponentRegistry>*)

这是令人困惑的输出。当实际呼叫和预期呼叫完全相同时,我无法理解为什么NSubstitute不满意。有线索吗?

1 个答案:

答案 0 :(得分:2)

正如已经说过的,RegisterApiControllers是一种扩展方法,只有虚拟成员可以被NSubstitute拦截。

但它并没有那么糟糕,它可以帮助你通过测试获得更清晰,松散耦合的设计。使用像Fakes或JustMock这样的工具,您可以模拟所有内容,并且它们不会强迫您使系统松散耦合。

我认为您的测试没用,您注册控制器的事情并不意味着您可以解决它们。我建议测试你可以解决它们。像这样:

[Test]
public void ResolvesServiceController()
{
    // Arrange
    var configuration = new HttpConfiguration();
    var containerBuilder = new ContainerBuilder();
    DependencyResolverConfig.Register(configuration, containerBuilder);

    // Act
    var controller = configuration.DependencyResolver.GetService(typeof (ServiceController));

    // Assert
    Assert.IsNotNull(controller);
} 

然后你可以进行进一步的重构,即创建一个Autofac模块,你可以在其中注册控制器及其依赖项,然后测试这个模块。