0

我正在尝试在现有代码库中隔离和测试特定类,该代码库派生自某个基础并具有我想模拟的私有类成员:

public class Derived : Base 
{ 
   protected Something<Other> _otherSomething = new Something<Other>();
}

具体来说,我想使用测试来验证Derived引发某些事件DoSomething以响应_otherSomething引发ItHappened事件。

为了实现这一点,我在我的测试项目中创建了一个MockedDerived类,它是Derived

public class MockDerived : Derived
{
   public Something<Other> OtherSomething 
   { 
      set { _otherSomething = value; } 
   }
}

我使用NSubstitute作为我的 MSTest 测试方法的一部分来模拟一个类,我想做这样的事情:

[TestMethod]
public void TestMethod1()
{
   var sub = Substitute.For<Something<Other>>();
   MockedDerived md = new MockedDerived();
   bool wasRaised = false;
   md.DoSomething += (sender, args) => wasRaised = true;
   md.OtherSomething = sub;
   sub.itHappened += Raise.Event<ItHappenedEventHandler<Other>>(new ItHappenedEventArgs<Other>());
   Assert.IsTrue(wasRaised);
}

我遇到的困难在于Base该类带来了相当多的包袱,即它创建了其他类的一些对象,并且这些对象具有一些计时器并最终涉及数据库。

它变得混乱。

我真正想做的就是确保这个Derived类表现出特定的行为并按预期做出响应。

关于如何将这种Derived行为的测试与混乱Base及其各种成员隔离开来的任何建议?也许我只是没有看到明显的解决方案。

4

2 回答 2

1

在不知道您的代码正在做什么的细节或您必须改变那里的内容的灵活性的情况下,我可以想到两种粗略的方法来尝试:将两者隔离BaseDerived从它们的公共依赖项中分离出来,或者打破继承链。

作为前者的一个例子,我们可以将导致问题的“行李”注入Base(我们也必须提供它Derived)。然后我们可以在测试中伪造它,以使我们的测试不受计时器和数据库的影响。

public class Base {
  public Base(DatabaseStuff d, TimerStuff t) { ... }
}
public class Derived : Base {
  public Derived(DatabaseStuff d, TimerStuff t, Something<Other> something) : base(d,t) {...}
}

对于第二个选项,我们可以尝试用组合替换继承。Base我们Derived可以引用 aBase并委托给它,而不是继承自。

public class Derived {  //TODO: Rename to `NotSoDerived` 
  public Derived(Base b, Something<Other> something) { ... }
  public ItHappenedEventHandler<Other> itHappened ...;
  public void SomeBaseMethod() {
    b.SomeBaseMethod(); // let b handle this call
  }
}

现在我们可以注入一个 fake Base(或者null <shudder>如果你的测试不会调用Base)和一个 mocked Something<Other>,我们可以单独测试那个方面Derived

如果您需要使用DerivedBase互换,那么您可以考虑提取一个IBase接口(如果这有意义的话),然后两者都Base可以Derived实现它。

于 2014-04-16T13:38:46.677 回答
1

您正面临测试遗留代码的情况,其中您的基类接受具体的依赖项而不是依赖于接口。您可能需要参考 Michael Feather 的“有效地使用遗留代码”一书中描述的 Sprout 方法和 Sprout 类。

于 2014-04-16T10:25:58.753 回答