使用Moq模拟ChannelFactory时出现TargetInvocationException

斯坦尼斯拉夫·维尔吉科夫斯基(Stanislav Verjikovskiy)

为什么TargetInvocationException在嘲笑时抛出ChannelFactory<IService>

public interface IService
{
    void Do();
}

public class Service : IService
{
    private ChannelFactory<IRemoteService> factory;

    public Service(ChannelFactory<IRemoteService> factory)
    {
        this.factory = factory;
    }

    public void Do()
    {
        using (var remote = factory.CreateChannel())
        {
            remote.DoRemote();
        }
    }
}

[TestFixture]
public class ChannelFactoryMoqTest
{
    private IService service;
    private Mock<ChannelFactory<IRemoteService>> factory;

    [Test]
    public void Test()
    {
        this.factory = new Mock<ChannelFactory<IRemoteService>>();

        this.service = new Service(this.factory.Object);
        // Calling Object on this.factory throws TargetInvocationException
    }
}

我想使用ChannelFactory依赖关系而不是简单的IRemoteService原因,在我看来,就并发而言,Service每个调用创建实例是更安全的

这是异常堆栈跟踪:

  System.Reflection.TargetInvocationException was unhandled by user code
  HResult=-2146232828
  Message=Exception has been thrown by the target of an invocation.
  Source=mscorlib
  StackTrace:
       at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
       at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
       at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
       at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
       at System.Activator.CreateInstance(Type type, Object[] args)
       at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyInstance(Type proxyType, List`1 proxyArguments, Type classToProxy, Object[] constructorArguments)
       at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
       at Moq.Proxy.CastleProxyFactory.CreateProxy(Type mockType, ICallInterceptor interceptor, Type[] interfaces, Object[] arguments)
       at Moq.Mock`1.<InitializeInstance>b__2()
       at Moq.PexProtector.Invoke(Action action)
       at Moq.Mock`1.InitializeInstance()
       at Moq.Mock`1.OnGetObject()
       at Moq.Mock.GetObject()
       at Moq.Mock.get_Object()
       at Moq.Mock`1.get_Object()
       at TR.Eikon.Services.AppVersion.Tests.Workflows.ChannelFactoryMoqTest.Test() in d:\Temp.cs:line 61
  InnerException: System.NullReferenceException
       HResult=-2147467261
       Message=Object reference not set to an instance of an object.
       Source=System.ServiceModel
       StackTrace:
            at System.ServiceModel.ChannelFactory.EnsureSecurityCredentialsManager(ServiceEndpoint endpoint)
            at System.ServiceModel.ChannelFactory.InitializeEndpoint(String configurationName, EndpointAddress address)
            at System.ServiceModel.ChannelFactory`1..ctor()
            at Castle.Proxies.ChannelFactory`1Proxy..ctor(IInterceptor[] )
       InnerException: 
恩科西

您收到此错误是因为ChannelFactory尝试创建与之关联的不存在的端点的实际代理。

我的建议是ChannelFactory<IRemoteService>在客户端所控制的界面后面隐藏/隔离客户端,以便您可以更好地管理所需的API。这样,您可以替换工厂,为客户端提供创建模拟而不是真实代理的模拟。

public interface IMyChannelFactory<TChannel> {
    TChannel CreateChannel();
}

...以后可以包装ChannelFactory<IRemoteService>...的实际实例

public class ChannelFactoryWrapper<TChannel> : IMyChannelFactory<TChannel> {
    private ChannelFactory<TChannel> factory;
    public ChannelFactoryWrapper(ChannelFactory<TChannel> factory) {
        this.factory = factory;
    }

    public TChannel CreateChannel() {
        return factory.CreateChannel();
    }
}

重构的服务类将引用新的模拟接口。

public class Service : IService {
    private IMyChannelFactory<IRemoteService> factory;

    public Service(IMyChannelFactory<IRemoteService> factory) {
        this.factory = factory;
    }

    public void Do() {
        using (var remote = factory.CreateChannel()) {
            remote.DoRemote();
        }
    }
}

...然后可以对您的测试进行重构和相应的测试...

[Test]
public void Should_Mock_ChannelFactory() {
    //Arrange
    var remoteService = new Mock<IRemoteService>();
    remoteService.Setup(m => m.DoRemote()).Verifiable();
    var factory = new Mock<IMyChannelFactory<IRemoteService>>();
    factory.Setup(f => f.CreateChannel()).Returns(remoteService.Object).Verifiable();
    var service = new Service(factory.Object);

    //Act
    service.Do();

    //Assert
    remoteService.Verify();
    factory.Verify();
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

使用Moq模拟ChannelFactory时出现TargetInvocationException

来自分类Dev

使用SemanticResultKey时出现TargetInvocationException

来自分类Dev

使用Moq进行模拟时,模拟返回null

来自分类Dev

使用Moq模拟GetEnumerator

来自分类Dev

尝试模拟Entity Framework上下文时抛出TargetInvocationException

来自分类Dev

使用Moq模拟ControllerBase请求

来自分类Dev

使用Moq模拟Fluent界面

来自分类Dev

使用 moq 模拟对 IQueryable 的调用

来自分类Dev

如何使用 moq 模拟 ActionExecutingContext

来自分类Dev

从Azure中的SOAP Web服务检索列表时出现TargetInvocationException

来自分类常见问题

使用Mockito模拟接口时出现空指针异常

来自分类Dev

使用Android模拟器时出现ReferenceError

来自分类Dev

在使用Moq和AutoFixture进行单元测试API时模拟HttpResponseMessage

来自分类Dev

使用Moq时,是否应该执行模拟接口实现的方法?

来自分类Dev

使用Moq模拟使用可选参数的方法

来自分类Dev

使用Moq模拟使用可选参数的方法

来自分类Dev

使用Moq模拟不安全的界面

来自分类Dev

使用Moq模拟方法的某些部分

来自分类Dev

在C#中使用Moq模拟

来自分类Dev

使用Moq模拟上下文

来自分类Dev

如何使用Moq从IConfiguration模拟GetConnectionString()?

来自分类Dev

使用Moq部分模拟类内部方法

来自分类Dev

使用Moq模拟访问者对象

来自分类Dev

使用Moq模拟方法的某些部分

来自分类Dev

使用Moq模拟自定义收藏

来自分类Dev

使用 MOQ 在 web api 中模拟 HttpContext

来自分类Dev

使用 Moq 模拟扩展 IList 的接口

来自分类Dev

使用Moq时出现奇怪的“对象引用未设置为对象实例”错误

来自分类Dev

在ASP.NET MVC单元测试中使用Moq模拟函数时无法返回非空字符串

Related 相关文章

热门标签

归档