如何在perl中测试ref条件?

时间:2011-06-15 07:36:05

标签: perl unit-testing ref

天儿真好,

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

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

无论我如何模仿我的物体,你似乎都无法愚弄ref()。我该如何测试呢?

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

1 个答案:

答案 0 :(得分: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时,这意味着返回并触及每个switchif / 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的使用。