使用Moq作为索引器属性会导致Castle出现InvalidCastException

时间:2012-06-06 21:32:57

标签: c# moq

尝试使用Moq设置索引器属性时,基础Castle库会抛出InvalidCastException。我使用的是Moq 4.0.10827,详情如下。如果有人能帮助我进行简单的测试(下面),请提前致谢。我正在用Moq重写单元测试,我正在尝试重新进行以下方法的测试:

public INetwork GetInputNetwork(IInputPortMgr inPortMgr)
{
    var port = inPortMgr[0];
    return port.InputNetwork;
}

IInputPortMgr接口如​​下:

public interface IInputPortMgr
{        
    IInputPort this[int index] { get; }
}

我写的测试(并试过很多变化)可以概括为:

[Test]
public void GetInputNetwork_Returns_InputNetwork_From_InputPort()
{
    var mockInPortMgr = new Mock<IInputPortMgr>();
    var mockInPort = new Mock<IInputPort>();
    var mockNet = new Mock<INetwork>();

    mockInPortMgr.Setup(m => m[0]).Returns(mockInPort.Object);  // exception here
    mockInPort.Setup(m => m.InputNetwork).Returns(mockNet.Object);

    // Assertions Here
}

但是在运行时单元测试失败,因为行抛出异常

mockInPortMgr.Setup(m => m[0]).Returns(mockInPort.Object);

例外的细节是:

System.InvalidCastException : Unable to cast object of type 'System.Collections.ObjectModel.ReadOnlyCollection`1[System.Reflection.CustomAttributeTypedArgument]' to type 'System.Array'.
at System.Reflection.Emit.CustomAttributeBuilder.EmitValue(BinaryWriter writer, Type type, Object value)
at System.Reflection.Emit.CustomAttributeBuilder.InitCustomAttributeBuilder(ConstructorInfo con, Object[] constructorArgs, PropertyInfo[] namedProperties, Object[] propertyValues, FieldInfo[] namedFields, Object[] fieldValues)
at Castle.DynamicProxy.AttributeUtil.CreateBuilder(CustomAttributeData attribute)
at Castle.DynamicProxy.AttributeUtil.<GetNonInheritableAttributes>d__0.MoveNext()
at Castle.DynamicProxy.Generators.MetaProperty.BuildPropertyEmitter(ClassEmitter classEmitter)
at Castle.DynamicProxy.Contributors.CompositeTypeContributor.ImplementProperty(ClassEmitter emitter, MetaProperty property, ProxyGenerationOptions options)
at Castle.DynamicProxy.Contributors.CompositeTypeContributor.Generate(ClassEmitter class, ProxyGenerationOptions options)
at Castle.DynamicProxy.Generators.InterfaceProxyWithoutTargetGenerator.GenerateType(String typeName, Type proxyTargetType, Type[] interfaces, INamingScope namingScope)
at Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors)
at Moq.Proxy.CastleProxyFactory.CreateProxy(ICallInterceptor interceptor, Type[] interfaces, Object[] arguments)
at Moq.Mock`1.<InitializeInstance>b__0()
at Moq.Mock`1.InitializeInstance()
at Moq.Mock`1.OnGetObject()
at Moq.Mock`1.get_Object()
at Tests.Psi.Type6.Fx.Type6Fixture.GetInputNetwork() in Type6Fixture.cs: line 293  

任何想法或任何人都可以指出我正确的方向?感谢。

1 个答案:

答案 0 :(得分:2)

它是Castle DynamicProxy版本中的bug,它被合并到moq二进制文件(Castle.Core 2.5.0.0)中。它看起来会影响接受params参数的属性。我假设IInputPort装饰有这样的属性,因为没有提供代码?

您可以使用最新版本的Castle.Core(3.0.0.0)(理想)编译moq。

或(不太理想),从Google Code下载最新的moq版本,其中包含未嵌入Castle.Core的moq.dll版本。在项目中引用此项和Castle.Core 3.0.0.0,并在app.config中添加以下绑定重定向。由于这是一个主要的升级点,我不能保证它的向后兼容性,但我用你的代码测试了这个(和IInputPort界面装饰了一个表明2.5.0.0中的bug的属性)并且它有效。

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Castle.Core" 
                          publicKeyToken="407dd0808d44fbdc" 
                          culture="neutral" />
        <bindingRedirect oldVersion="2.5.0.0" 
                         newVersion="3.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>