单元测试:如何打破本地对象依赖?

发布于 2024-12-08 05:26:21 字数 538 浏览 0 评论 0原文

我有如下代码:

class B;

class A
{
  A()
  {
  }
  bool MethodA()
  {
    B *pB = new B();
    bool bRet = pB->SomeFunction();
    // remaining logic;
    return bRet;
  }
  ~A(){}
};

我需要为 MethodA 编写测试。所以我认为我需要打破对类 B 的依赖。最好的方法是什么?如果它是一个成员变量,我可以通过构造函数注入一个存根。是否有任何解决方案不涉及生产代码的更改? 如果需要改变,最好的方法是什么?

我使用 NUnit 并且正在处理一些非托管代码。请帮忙!

编辑:我错过了另一个令人头痛的问题! B 类是一个 C++ 类,我不应该更改它的实现。类 A 在 C++/CLI 中,它充当 B 的包装器。所以我认为这抑制了 B 的接口的可能性,因为我无法接触 B。

I've a code like following:

class B;

class A
{
  A()
  {
  }
  bool MethodA()
  {
    B *pB = new B();
    bool bRet = pB->SomeFunction();
    // remaining logic;
    return bRet;
  }
  ~A(){}
};

I need to write tests for MethodA. So I think I need to break the dependency on class B. What is the best way to do it? If it was a member variable, I could have injected a stub via constructor. Is there any solution that doesn't involve change in production code?
If a change is necessary, what's the best way?

I use NUnit and is working on some unmanaged code here. Please help!

edit: There is another headache that I missed! class B is a C++ class which I shouldn't change its implementation. class A is in C++/CLI, which acts as wrapper to B. So I think that inhibits the probability of an Interface for B as I cannot touch B.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光清浅 2024-12-15 05:26:21

不。没有任何解决方案不包括更改该设计,主要是因为该设计糟糕。 A 及其依赖项 B 紧密耦合,这使得面向对象编程变得非常糟糕:您需要反转依赖项的控制。测试只是该设计不好的原因之一,但并不是唯一的原因。可移植性、灵活性、关注点分离是其他因素。

使其可测试并使其变得更好的最佳方法(唯一的好方法)是依赖注入
您需要使用构造函数(将 B 的接口作为参数)或 setter 将 B 注入 A 中。无论谁控制 A(并执行 new A()),都应该将依赖项 B 传递给它(new A(new B()),或 A. setB(新B()))。

一旦完成,对该方法进行单元测试将变得非常容易。

No. There is no solution that doesn't include changing that design, mostly because that design is bad. A and its dependency B are tightly coupled, which makes as bad as it gets in terms of object-oriented programming: you need to invert the control of dependencies. Testing is only one reason why that design is bad, but it's not the only one. Portability, flexibility, separation of concerns, are other.

The best way (the only good way) to make it testable, and to make it better, is dependency injection.
You need to inject B into A, using either a constructor (that takes an interface to B as a parameter) or a setter. And whoever controls A (and does a new A()) should pass the dependency B to it (new A(new B()), or A.setB(new B())).

Once that is done, unit-testing the method will become very easy.

白云不回头 2024-12-15 05:26:21

如果不进行更改,您就无法做到这一点,但您可以执行以下操作:

class A
{
  A()
  {
  }


  A(B *b)
  {
     pB = b;
  }

  B *pB;

  bool MethodA()
  {
    if (*pB == null) {
      *pB = new B();
    }
    bool bRet = pB->SomeFunction();
    // remaining logic;
    return bRet;
  }
  ~A(){}
};

至少在 C# 中,我认为您正在编写此内容。没有处理太多指针,所以我不确定我的语法是否正确,但基本上的想法是对 pB 进行延迟初始化,以允许您注入依赖项(如果您愿意)但不会破坏当前行为。您可以更花哨一点,将 A 的备用构造函数设置为内部,然后使用 InternalsVisibleTo 属性仅将其显示给您的测试类。

You can't do this without making a change, but you could do something like:

class A
{
  A()
  {
  }


  A(B *b)
  {
     pB = b;
  }

  B *pB;

  bool MethodA()
  {
    if (*pB == null) {
      *pB = new B();
    }
    bool bRet = pB->SomeFunction();
    // remaining logic;
    return bRet;
  }
  ~A(){}
};

At least in C# which is what I think you are writing. Haven't dealt much with pointers, so I'm not sure if I got the syntax right, but basically the idea is to do lazy initialization of pB to allow you to inject a dependency if you'd like but not break the current behavior. You could get a bit fancier and make the alternate constructor for A internal and then use the InternalsVisibleTo attribute to only show it to your test classes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文