4

节日,

我正在尝试对使用如下语句的函数进行单元测试:

unless($this->_doc_type eq ref($this->_doc_instance)) {
    # Do something
} 

无论我如何模拟我的对象,您似乎都无法愚弄 ref()。我应该如何进行测试?

  • 有一个ref()调用的私有函数CORE::ref()
  • CORE::ref尝试在我的单元测试中覆盖?
  • ???
4

1 回答 1

3

在过去糟糕的日子里,我们有形式的代码

switch (item->type) {
  case FOO:
    do_foo(item);
    break;

  case BAR:
    do_bar(item);
    break;

  default:
    handle_unknown_type(item->type, __FILE__, __LINE__);
    break;
}

这种明确检查项目类型然后分支到不同功能的模式在系统的源代码中重复了很多次。

当需要BAZ在组合中添加新类型时,这意味着要返回并触及每一个switch, if/else链或任何其他涉及 的条件item->type

这是一个很大的痛苦。

面向对象的语言吸收了这种模式,因此程序员不必到处重新实现它,也不必在这种低级管道上浪费脑力资源。当据称面向对象的代码渴望过去的糟糕时光时,例如

unless ($this->_doc_type eq ref($this->_doc_instance)) { ... }

这是一种强烈的代码气味。

我的第一个建议是重新设计生产代码。条件内部发生了什么?该代码的意图是什么?

我假设您一直在为_doc_instance. 为了在重构代码之前获得测试支持,我将研究如何更改从返回的值_doc_type,我还假设这不是一个简单的 getter。对上下文一无所知,一种方法是创建一个测试子类。

假设您要测试的课程是My::Container. 如果您可以为这个特定的测试使用伪造的文档(只有真实文档的表面外观),请按照以下内容编写代码

package Test::My::Container_Canned_Type;

use base 'My::Container';

sub _doc_type { "Test::Fake::Document" }

1;

然后在你的测试中,使用它

my $doc = bless {} => "Test::Fake::Document";
my $c   = Test::My::Container_Canned_Type->new($doc, ...);

如果我对您的代码结构猜错了,请提供更多上下文,以便我们为您提供更多有用的建议!

发现自己处于这个困境是一个很好的教训,为什么首先编写测试是有帮助的。通过设计,您消除了挠头并想知道如何测试一个奇怪的实现的情况。

概括

  • 不,不要试图修改ref工作方式。
  • 在可能的范围内,消除ref生产代码中的使用。
于 2011-06-15T13:21:21.947 回答