[英]How to mock ModelMetadata class using NSubstitute?
在我的库中,我有一个简单的类:
public class FormDataJsonBinderProvider : IModelBinderProvider
{
// code ommited
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
// some logic
}
}
我想测试它,但要这样做,我必须以某种方式模拟ModelMetadata
( context.Metadata
是ModelMetadata
的类型),这是一个具有该签名的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.