繁体   English   中英

如何使用 NSubstitute 模拟 ModelMetadata 类?

[英]How to mock ModelMetadata class using NSubstitute?

在我的库中,我有一个简单的类:

public class FormDataJsonBinderProvider : IModelBinderProvider 
{
    // code ommited

    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        // some logic
    }
}

我想测试它,但要这样做,我必须以某种方式模拟ModelMetadatacontext.MetadataModelMetadata的类型),这是一个具有该签名的abstract类:


public abstract class ModelMetadata : IEquatable<ModelMetadata?>, IModelMetadataProvider 
{
    // some props and methods

    internal virtual bool PropertyHasValidators => false; // problematic property :(
}

在我的测试中,我有

[Test]
public void GetBinder_SimpleType_ShouldThrowException() 
{
    // Arrange
    var metadata = Substitute.For<ModelMetadata>();
    metadata.IsComplexType.Returns(false);
}

我得到System.ArgumentException : Can not instantiate proxy of class: Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata. Could not find a parameterless constructor. (Parameter 'constructorArguments') System.ArgumentException : Can not instantiate proxy of class: Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata. Could not find a parameterless constructor. (Parameter 'constructorArguments') System.ArgumentException : Can not instantiate proxy of class: Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata. Could not find a parameterless constructor. (Parameter 'constructorArguments')这是完全公平的。

所以。 我制作了一个TestModelMetadata类:

public abstract class TestModelMetadata : ModelMetadata {
    public TestModelMetadata() : base(new ModelMetadataIdentity()) { }

    public new virtual bool IsComplexType { get; }

    public override IReadOnlyDictionary<object, object> AdditionalValues { get; }
    // More overridden props
}

我正在这样使用它:

public void GetBinder_SimpleType_ShouldThrowException() 
{
    // Arrange
    var metadata = Substitute.For<TestModelMetadata>();
    metadata.IsComplexType.Returns(false);
}

在这里我得到一个奇怪的例外:

System.TypeLoadException : Method 'get_PropertyHasValidators' on type 'Castle.Proxies.TestModelMetadataProxy' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is overriding a method that is not visible from that assembly.
   at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
   at System.Reflection.Emit.TypeBuilder.CreateTypeInfo()
   at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
   at Castle.DynamicProxy.Generators.BaseClassProxyGenerator.GenerateType(String name, INamingScope namingScope)
   at Castle.DynamicProxy.Generators.BaseProxyGenerator.<>c__DisplayClass13_0.<GetProxyType>b__0(CacheKey cacheKey)
   at Castle.Core.Internal.SynchronizedDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Castle.DynamicProxy.Generators.BaseProxyGenerator.GetProxyType()
   at Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
   at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
   at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
   at NSubstitute.Proxies.CastleDynamicProxy.CastleDynamicProxyFactory.CreateProxyUsingCastleProxyGenerator(Type typeToProxy, Type[] additionalInterfaces, Object[] constructorArguments, IInterceptor[] interceptors, ProxyGenerationOptions proxyGenerationOptions)
   at NSubstitute.Proxies.CastleDynamicProxy.CastleDynamicProxyFactory.GenerateTypeProxy(ICallRouter callRouter, Type typeToProxy, Type[] additionalInterfaces, Object[] constructorArguments)
   at NSubstitute.Proxies.CastleDynamicProxy.CastleDynamicProxyFactory.GenerateProxy(ICallRouter callRouter, Type typeToProxy, Type[] additionalInterfaces, Object[] constructorArguments)
   at NSubstitute.Core.SubstituteFactory.Create(Type[] typesToProxy, Object[] constructorArguments, Boolean callBaseByDefault)
   at NSubstitute.Core.SubstituteFactory.Create(Type[] typesToProxy, Object[] constructorArguments)
   at NSubstitute.Substitute.For(Type[] typesToProxy, Object[] constructorArguments)
   at NSubstitute.Substitute.For[T](Object[] constructorArguments)

所以问题是:

如何模拟ModelMetadata类以在我的测试中使用?

您应该能够告诉 NSubstitute 使用ModelMetadata上的现有构造函数之一,而不是仅为测试创建一个TestModelMetadata类,如下所示:

[Test]
public void GetBinder_SimpleType_ShouldThrowException() 
{
    // Arrange
    var metadata = Substitute.For<ModelMetadata>(new ModelMetadataIdentity());
    metadata.IsComplexType.Returns(false);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM