【问题标题】:Unit testing passing arguments to base constructor单元测试将参数传递给基本构造函数
【发布时间】:2012-07-27 15:35:39
【问题描述】:

我有以下代码:

        using System;
        using NUnit.Framework;
        using Rhino.Mocks;

        public class A
        {
        }

        public class B
        {
        }

        public interface IStatementExecutor
        {
            void Exec(string statement);
        }

        public abstract class Foo<T>
        {
            private readonly IStatementExecutor _statementExecutor;
            private readonly string _targetSegment;

            protected Foo(IStatementExecutor statementExecutor, string targetSegment)
            {
                _statementExecutor = statementExecutor;
                _targetSegment = targetSegment;
            }

            public void Update(T item)
            {
                _statementExecutor.Exec("sp_" + _targetSegment + "Update");
            }
        }

        public class Bar : Foo<A>
        {
            public Bar(IStatementExecutor statementExecutor)
                : base(statementExecutor, "ATable")
            {
            }
        }

        public class Baz : Foo<B>
        {
            public Baz(IStatementExecutor statementExecutor)
                : base(statementExecutor, "BTable")
            {
            }
        }

        [TestFixture]
        public class Foo_Tests
        {
            [Test]
            public void Update_CallsStatementExecutorWithTableName()
            {
                const string tableName = "TestTable";
                var mockStatementExecutor = MockRepository.GenerateMock<IStatementExecutor>();
                mockStatementExecutor.Expect(m => m.Exec("sp_" + tableName + "Update"));
                var sut = MockRepository.GeneratePartialMock<Foo<A>>(mockStatementExecutor, tableName);
                var testModel = new A();


                sut.Update(testModel);

                mockStatementExecutor.AssertWasCalled(m => m.Exec("sp_" + tableName + "Update"));
            }
        }

我已经对基类Foo&lt;T&gt; 进行了单元测试。由于已经涵盖了基类,我不想为派生类BarBaz 编写相同的测试。

我在派生类中唯一真正关心的是正确的字符串target 被传递给基类。

我正在努力解决如何在不破坏派生类封装或编写冗余单元测试的情况下对其进行单元测试。

那么,问题是,如何测试target 参数的派生类是否将正确的值传递给基类?

(如果您的答案是“使用合成...”,请使用上面修改的代码示例进行备份。

谢谢!

【问题讨论】:

  • “ATable”是否在您的实际情况下硬编码?是常量吗?
  • 能否请您发布基类Foo 的单元测试?我看到它是一个 abstract 类(无法创建对象),而 _target 是一个私有变量(在测试中无法访问),很想知道您是如何对其进行单元测试的。
  • 进一步@channs 评论 - Foo 的方法正在调用控制台,那么您如何测试这些方法?

标签: c# unit-testing abstract-base-class


【解决方案1】:

我认为我更有可能通过 Bar 和 Baz 上的其他方法进行测试,因为如果你将 ZTable 而不是 BTable 放在那里,你会预料到会发生一些不好的事情

您可以向 Foo 添加一个方法,该方法将返回曾经传递给它的内容

然后在创建后代后调用它并根据预期值进行验证。

或者你可以做类似的事情

public class Bar : Foo<A>     
{         
  private static String _tableName = "ATable";
  public String  TableName {get {return _tableName;}}
  public Bar() : base(_tableName)         
  {         
  }     
} 

然后你可以测试 testBar.TableName

另一个选项是 T 是具有 TableName 属性的结构或类,那么您就不需要 Bar 和 Baz 后代,仅此而已。

【讨论】:

    【解决方案2】:

    您的 Foo 和 Bar 单元测试方法可以调用包含通用测试代码的辅助方法。

    【讨论】:

      【解决方案3】:

      您可以通过多种方式做到这一点。一种方法是使用像 TypeMock 这样的模拟框架来有效地模拟基类,从而从 TypeMock 获取有关内部变量的更多信息。

      不过,从您的帖子中并不清楚,为什么基类被 bar 类用于特定原因很重要。这不清楚,因为您无法对其进行测试。即没有可以监控的外部行为来保证Bar 以预期的方式使用Foo。您可以重定向控制台输出,然后监视该输出以进行验证。但是,我认为这并不是您真正想要的。

      您应该提供一个更可测试的示例;不只是输出文本的东西,还有你可以通过测试观察到的真实行为。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-04-04
        • 2019-01-06
        • 1970-01-01
        • 1970-01-01
        • 2014-12-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多