如何使用一种功能测试我的包?

Posted

技术标签:

【中文标题】如何使用一种功能测试我的包?【英文标题】:How can I test my package with one function? 【发布时间】:2020-09-19 02:01:34 【问题描述】:

我制作了一个编译良好的包,但是当我尝试对其进行测试时,它给了我“无效的数据类型”。 我尝试了两种不同的方法,第一种是这样的

select pkg_contabilidad.f_totalizar_Detalle(100) FROM DUAL;

它给了我 ORA-00902 '无效数据类型' 我也试过这个

DECLARE 
    TYPE r_registro IS RECORD
    (rubro_contable CN_RUBROS_CONTABLES.COD_RUBRO%TYPE,
    tipo VARCHAR2(1),
    monto NUMBER(16));
    resultao r_registro;
    numero NUMBER :=100;
BEGIN
    resultao := pkg_contabilidad.f_totalizar_detalle(numero);
END;

它给了我另一个错误 PLS-00382 '表达式类型错误' 我不知道我做错了什么,因为我的函数只接收一个参数并且是 NUMBER 类型,所以我不知道我的错误在哪里。我会留下我的包裹代码以防万一

CREATE OR REPLACE PACKAGE pkg_contabilidad AS
TYPE r_registro IS RECORD
(rubro_contable CN_RUBROS_CONTABLES.COD_RUBRO%TYPE,
tipo VARCHAR2(1),
monto NUMBER(16));
TYPE t_detalle IS TABLE OF
r_registro INDEX BY BINARY_INTEGER;
FUNCTION f_totalizar_detalle(p_clave NUMBER)RETURN t_detalle;
END pkg_contabilidad;
/
CREATE OR REPLACE PACKAGE BODY pkg_contabilidad AS
B_detalle t_detalle;
i integer :=1;
FUNCTION f_totalizar_detalle(p_clave NUMBER) RETURN t_detalle IS
    v_detalle t_detalle;
    CURSOR c_facturado IS 
    SELECT c.cod_rubro, 'H', CASE WHEN SUM(d.gravada)=0 THEN SUM(d.iva) ELSE SUM(d.gravada) END
    FROM fn_documentos_det d JOIN fn_conceptos c ON d.cod_concepto = c.cod_concepto
    WHERE d.clave_doc=p_clave
    GROUP BY c.cod_rubro;
    
    CURSOR c_datos IS
    SELECT SUM(d.total_doc), 'D',r.cod_rubro 
    FROM fn_documentos d JOIN fn_cajas_ctas r ON d.num_caja_cta = r.num_caja_cta
    WHERE d.clave_doc = p_clave
    GROUP BY r.cod_rubro;
BEGIN
    open c_datos;
    LOOP
    FETCH c_datos INTO v_detalle(1);
    END LOOP;
    CLOSE c_datos;
    FOR fila IN c_facturado LOOP
    i := i + 1;
    v_detalle(i) := fila;
    END LOOP;
END;
END PKG_CONTABILIDAD;

【问题讨论】:

【参考方案1】:

函数返回一个pkg_contabilidad.t_detalle,所以测试需要:

declare
    resultao pkg_contabilidad.t_detalle;
    numero   number := 100;
begin
    resultao := pkg_contabilidad.f_totalizar_detalle(numero);
end;

它在 SQL 中不起作用,因为pkg_contabilidad.t_detalle 是 PL/SQL 类型,而不是 SQL 类型 (create or replace type)。数据库可以进行一些自动转换,但是还是有限制的。

顺便说一句,这个循环永远不会完成,因为它缺少exit 条件:

open c_datos;
loop
    fetch c_datos into v_detalle(1);
end loop;
close c_datos;

【讨论】:

【参考方案2】:

您的函数返回一个 PL/SQL 表类型,其中包含一个 PL/SQL 记录类型的表,该表在您的包中定义,普通 SQL 不知道也无法显示 - 因此您的数据类型无效错误.如果您需要调用该函数并从 SQL 访问数据,您可以创建模式级对象和集合类型。

在您的匿名块中,您是在声明一个 记录类型。这对您来说看起来是一样的,因为结构是相同的,但是 Oracle 期望函数返回的确切类型。这使您的测试代码更短更简单。但是您也试图将整个集合返回到单个记录中。

DECLARE 
    l_detalle pkg_contabilidad.t_detalle;
    l_registro pkg_contabilidad.r_registro;
    l_idx pls_integer;
    numero NUMBER :=100;
BEGIN
    l_detalle := pkg_contabilidad.f_totalizar_detalle(numero);
    l_idx := l_detalle.FIRST;
    WHILE l_idx is not null LOOP
        l_registro := l_detalle(l_idx);
        -- do something with this record
        dbms_output.put_line(l_registro.tipo);
        l_idx := l_detalle.NEXT(l_idx);
    END LOOP;
END;

db<>fiddle 带有虚拟光标。

你的函数有点奇怪,可能没有做你想要的;但也有两个致命的问题:它没有返回任何东西,并且它有一个无限循环。我已经为小提琴修复了这些,但没有其他任何东西,因为这似乎是一种练习。

【讨论】:

以上是关于如何使用一种功能测试我的包?的主要内容,如果未能解决你的问题,请参考以下文章

当用户使用 pip 卸载我的包时如何运行脚本?

如何在golang中测试主要的包功能?

如何在 Laravel5 中使用我的包

如何将 testthat 测试应用于我的包中与特定命名模式匹配的所有函数?

如何在 Laravel 项目中为我自己的包运行 php 测试?

如何使用 laravel 6 在我的包中使用 auth 进行自定义防护?