【问题标题】:Insert values in class without explicit writing them在类中插入值而不显式写入它们
【发布时间】:2019-07-09 08:16:23
【问题描述】:

我有一些庞大的类,不想将它们全部写出来进行测试,因为这是一项巨大的工作,而且我可能会忘记一些导致测试无效的值。

Messages = new List<Request.Notif.NotifRuleMessages>
{
    new Request.Notif.NotifRuleMessages
    {
        Code = 1234,
        Message = new List<Request.Notif.NotifRuleMessagesMessage>
        {
            new Request.Notif.NotifMessagesMessage
            {
                Status = new Request.Notif.NotifMessagesMessageStatus
                {
                    Code = 1,
                    Bool = true,
                    Test1 = "Test",
                    Test2 = "Test"
                },
                Rules = new List<Request.Notif.NotifMessagesMessageRule>
                {
                    new Request.Notif.NotifMessagesMessageRule
                    {
                        Lengths = new Request.Notif.NotifMessagesMessageRuleLength
                        {
                            Lenght = 1,
                            Lengths = new List<Request.Notif.NotifMessagesMessageRuleLengthLength>
                            {
                                new Request.Notif.NotifMessagesMessageRuleLengthLength
                                {
                                    Type = "Test",
                                    Value = 1
                                }
                            }
                        },
                        Status = new List<Request.Notif.NotifMessagesMessageRuleStatus>
                        {
                            new Request.Notif.NotifMessagesMessageRuleStatus
                            {
                                Test1 = "Test",
                                Test2 = "Test"

有没有办法自动用10 填充所有int 值,用Test 自动填充所有string 值,尤其是所有objects 使用正确的类无需单元测试和外部库

【问题讨论】:

  • 您为什么认为会存在一些发生应用认为可以接受的默认值?
  • @Damien_The_Unbeliever 因为{ get; set; } 也存在,这对于纯编码来说是不必要的,只是帮助开发人员:) 并且可能有一些东西可以初始化整个类(带有子类)
  • 我认为最好的办法是使用反射实现自己的解决方案。我怀疑那里有一个标准的解决方案。需要注意的一件事是您的结构是否是递归的。
  • @Xerillio 我无法想象有反射的解决方案,你能给我举个例子吗?不,不涉及递归。

标签: c# class testing automation


【解决方案1】:

使用反射,您可以递归地填充对象并设置您选择的任何默认值。一个可以为您执行此操作的辅助函数的小示例:

void SetDefaults(object testObj)
{
    var props = testObj.GetType().GetProperties();
    foreach (var prop in props)
    {
        if (prop.GetSetMethod() == null)
        {
            continue;
        }

        var propType = prop.PropertyType;
        if (propType == typeof(int))
        {
            prop.SetValue(testObj, 1);
        }
        else if (propType == typeof(bool))
        {
            prop.SetValue(testObj, false);
        }
        // More conditions...
        else
        {
            var ctor = propType.GetConstructor(Type.EmptyTypes);
            var propertyObject = ctor.Invoke(new object[0]);
            SetDefaults(propertyObject);
            prop.SetValue(testObj, propertyObject);
        }
    }
}

如您所见,如果您的对象树使用没有默认构造函数(无参数构造函数)的类型,您需要在else 条件中添加一些更复杂的逻辑。基本上这里发生的事情是依赖注入框架中发生的事情的一个非常简化的版本。

要使用它,请执行以下操作:

void Main()
{
    TestObject obj = new TestObject();
    SetDefaults(obj);

    Console.WriteLine(obj);
}

class TestObject {
    public int MyInt { get; set; }
    public SubTestObject SubObj { get; set; }
}

class SubTestObject {
    public int MyOwnInt { get; set; }
    public bool MyBoolGetter => 1 > 0;
}

【讨论】:

  • 这太棒了! 但是我收到了一个错误,因为一个类是 public bool ShouldSerializeName { return Name &gt; 0; } 是。我认为这是因为它无法为其设置值。 TargetParameterCountException 由不同的参数计数抛出。对此的任何解决方案,网络都无法帮助我。
  • @Daniel 关于ShouldSerializeName,根据您想要发生的情况,您可以检查prop.GetSetMethod() == null 并跳过它。我不确定你为什么会看到TargetParameterCountException,除非其中一个类有类似索引器的东西,它需要多个参数。我需要更多的上下文来弄清楚这一点。
  • ShouldSerialize{Name} 变量标识变量Name 是否应由XmlSerializer 序列化,但我将为此打开another question,因为它不在此范围内:)跨度>
猜你喜欢
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 2017-10-04
  • 2011-01-11
  • 1970-01-01
  • 2021-03-18
相关资源
最近更新 更多