简体   繁体   English

在具有用于测试(C#)的内部设置器的类中设置属性

[英]Setting a property within a class that has an internal setter for use in testing (C#)

I'm using NJsonSchema to validate JSON input. 我正在使用NJsonSchema来验证JSON输入。

I have a small class that takes a collection of ValidationError objects and creates more user friendly error messages using the contents of each validation error. 我有一个小类,它接收ValidationError对象的集合,并使用每个验证错误的内容创建更用户友好的错误消息。

I want to be able to write unit tests for this class, however I have came across a problem. 我希望能够为此类编写单元测试,但是遇到了一个问题。 One of the message handlers within my class has the responsibility of handling NotInEnumeration errors, and for this it uses the Enumeration property within the JsonSchema4 object held within the ValidationError and creates a nicely formatted error message. 我类中的消息处理程序之一负责处理NotInEnumeration错误,为此,它使用ValidationError内JsonSchema4对象内的Enumeration属性并创建格式正确的错误消息。

When writing a test for this particular handler I discovered that the following is illegal: 为该特定处理程序编写测试时,我发现以下内容是非法的:

JsonSchema4 enumSchema = new JsonSchema4();
enumSchema.Enumeration = new List<object>{ "A", "B", "C" };

This is because the Enumeration property has an internal setter. 这是因为Enumeration属性具有内部设置器。

I need to be able to set the enumeration of a validation error as the object needs to be passed through to the ValidationError's constructor, which is then read later on by my handler, as below. 我需要能够设置验证错误的枚举,因为该对象需要传递给ValidationError的构造函数,然后由我的处理程序稍后将其读取,如下所示。

private string NotInEnumerationHandler(ValidationError error)
        {
            var userFriendlyErrorString = "Answer must be within range: ";
            var enumString = "[" + string.Join<object>(", ", error.Schema.Enumeration) + "]";
            userFriendlyErrorString += enumString;
            return userFriendlyErrorString;
        }

I cannot mock the JsonSchema4 object using moq as moq doesn't allow mocking of non-virtual methods. 我无法使用moq模拟JsonSchema4对象,因为moq不允许模拟非虚拟方法。

Essentially the details aren't really important, but I'd like to know if there's any way of setting an internal setter so that I can test this particular method within my class. 从本质上讲,细节并不是很重要,但是我想知道是否有任何方法可以设置内部设置器,以便可以在类中测试此特定方法。

JsonSchema4.Enumeration is an ICollection<Object> . JsonSchema4.Enumeration是一个ICollection<Object>

Therefore I don't need to set the value of Enumeration to a new colletion, I can just add the items I want into the existing one. 因此,我不需要将Enumeration的值设置为新的集合,只需将所需的项添加到现有项中即可。

You can use reflection to set, first you need to get the property info of the property and then set the value to the instance you created. 您可以使用反射进行设置,首先需要获取属性的属性信息,然后将值设置为创建的实例。

var enumSchema = new JsonSchema4();
var propertyInfo = typeof(JsonSchema4).GetProperty("Enumeration", BindingFlags.Public | BindingFlags.Instance);
propertyInfo.SetValue(enumSchema, new List<object> { "A", "B", "C" });

And this is how you can verify it worked 这就是您可以验证它是否有效的方式

Console.WriteLine(propertyInfo.GetValue(enumSchema, null));

You could make some extension method to provide you the "Enumeration" property in your test assembly. 您可以使用某种扩展方法在测试程序集中为您提供“枚举”属性。

This is not a complete answer, I just had too much to put in a comment and also it doesn't format correctly. 这不是一个完整的答案,我只是在评论中放了太多,而且格式不正确。 Here's a sample of what your AssemblyInfo.cs should look like: 这是您的AssemblyInfo.cs外观示例:

using System.Reflection;
using System.Runtime.CompilerServices;

[assembly: AssemblyTitle("Assembly.Fully.Qualified.Name")]
[assembly: AssemblyDescription("")]

#if DEBUG
[assembly: InternalsVisibleTo("Assembly.Fully.Qualified.Name")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
#endif

You need the bottom of the two Attributes DynamicProxyGenAssembly2 in order for Moq to be able to see the internals. 您需要两个属性DynamicProxyGenAssembly2的底部,以便Moq能够看到内部结构。 You might not need a Debug and Release switch in which case don't bother with the #if DEBUG section. 您可能不需要Debug和Release开关,在这种情况下,请不要担心#if DEBUG部分。

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

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