【问题标题】:How to mock a protected field?如何模拟受保护的字段?
【发布时间】:2010-11-22 21:10:15
【问题描述】:

我正在尝试模拟 NodeIdGenerator 类中的受保护字段。我想在构造函数中设置字段的值,然后调用属于NodeIdGeneratorGetNext()方法。

我很确定我的测试没问题:

public class NodeIdGeneratorTests
{

    [Fact(DisplayName = "Throws OverflowException when Int32.MaxValue " +
        "IDs is exceeded")]
    public void ThrowsOverflowExceptionWhenInt32MaxValueIdsIsExceeded()
    {
        var idGenerator = new NodeIdGeneratorMock(Int32.MaxValue);
        Assert.Throws(typeof(OverflowException), 
            () => { idGenerator.GetNext(); });
    }

    /// <summary>
    /// Mocks NodeIdGenerator to allow different starting values of 
    /// PreviousId.
    /// </summary>
    private class NodeIdGeneratorMock : NodeIdGenerator
    {
        private new int? _previousId;

        public NodeIdGeneratorMock(int previousIds)
        {
            _previousId = previousIds;
        }
    }

}

我的问题出在模拟课上。当我在测试中调用GetNext() 时,它使用属于超类的_previousId 对象,而不是我希望它使用的对象(在模拟类中)。

那么,如何模拟受保护的字段?

PS:我已经阅读了this question,但我似乎无法理解它!

【问题讨论】:

    标签: c# unit-testing mocking bdd xunit.net


    【解决方案1】:

    您发布的代码将_previousId 声明为new,因此它隐藏了基类的字段 - 它不会覆盖它。当您调用GetNext 时,基类不会使用该值,它将使用自己的字段。

    尝试删除您的声明并仅访问基类的受保护字段。

    【讨论】:

    • 哈哈,这么简单。谢谢。我刚刚删除了private new int? _previousId; 行,嘿,快!
    【解决方案2】:

    如果可能,最好将 previousId 设为虚拟属性并覆盖模拟中的 getter:

    public class NodeIdGenerator
    {
        protected virtual int? PreviousId { ... }
    }
    
    private class NodeIdGeneratorMock : NodeIdGenerator
    {
        protected override int? PreviousId
        {
            get { return _previousId; }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-01-08
      • 1970-01-01
      • 2011-07-18
      • 1970-01-01
      • 2012-10-13
      • 2016-03-09
      • 2016-05-29
      • 1970-01-01
      相关资源
      最近更新 更多