使用matlab测试框架对异常执行单元测试时发生错误

时间:2019-10-30 20:26:35

标签: matlab unit-testing exception

我在文件夹+WTrade/+Database/@PostgreSQLConnectionOptions中有以下课程:

classdef PostgreSQLConnectionOptions < handle

  properties (Access = private)
    databaseHost
  end

  methods (Access = public)

    function this = PostgreSQLConnectionOptions()
      this.databaseHost = "";
    end

    function setHostname(this, name)
      if ~isstring(name)
        me = MException("WTrade:invalidParameter", "WTrade.Database.PostgreSQLConnectionOption.setHostname: name must be a string");
        throw(me);
      end
      if 1 ~= length(name)
        me = MException("WTrade:invalidParameter", "WTrade.Database.PostgreSQLConnectionOption.setHostname: name array size must be 1");
        throw(me);
      end

      this.databaseHost = name;
    end

  end
end

我想对此课程进行单元测试。我有以下测试课

classdef PostgreSQLConnectionOptionsTest < matlab.unittest.TestCase

  methods (Test)

    function testWrongHostnameArray(this)
      options = WTrade.Database.PostgreSQLConnectionOptions();
      hostName = ["h1" "h2"];
      this.verifyError(options.setHostname(hostName), 'WTrade:invalidParameter');
    end

  end
end

当我尝试使用以下脚本运行测试时:

import matlab.unittest.TestSuite
import matlab.unittest.constraints.Throws;

databaseSuite = TestSuite.fromFolder("tests/WTrade/Database");
result = run(databaseSuite);

我收到以下错误:

>> runtests('PostgreSQLConnectionOptionsTest','ProcedureName','testWrongHostnameArray')
Running PostgreSQLConnectionOptionsTest
32        options = WTrade.Database.PostgreSQLConnectionOptions();

================================================================================
Error occurred in PostgreSQLConnectionOptionsTest/testWrongHostnameArray and it did not run to completion.
    ---------
    Error ID:
    ---------
    'MATLAB:TooManyOutputs'
    --------------
    Error Details:
    --------------
    Error using WTrade.Database.PostgreSQLConnectionOptions/setHostname
    Too many output arguments.

    Error in PostgreSQLConnectionOptionsTest/testWrongHostnameArray (line 34)
          this.verifyError(options.setHostname(hostName), 'WTrade:invalidParameter');
================================================================================
.
Done PostgreSQLConnectionOptionsTest
__________

Failure Summary:

     Name                                                    Failed  Incomplete  Reason(s)
    =======================================================================================
     PostgreSQLConnectionOptionsTest/testWrongHostnameArray    X         X       Errored.

ans = 

  TestResult with properties:

          Name: 'PostgreSQLConnectionOptionsTest/testWrongHostnameArray'
        Passed: 0
        Failed: 1
    Incomplete: 1
      Duration: 2.0606
       Details: [1×1 struct]

Totals:
   0 Passed, 1 Failed (rerun), 1 Incomplete.
   2.0606 seconds testing time.

我不了解'MATLAB:TooManyOutputs'错误。我已经在matlab中直接尝试了该方法,并且效果符合预期;我测试该参数是否为字符串,如果不是,它将引发异常。

当我运行以下命令时:

a = WTrade.Database.PostgreSQLConnectionOptions
a.setHostname(["p1", "p2")

我得到了我所期望的错误。

Error using WTrade.Database.PostgreSQLConnectionOptions/setHostname (line 43)
WTrade.Database.PostgreSQLConnectionOption.setHostname: name array size must be 1

那么,为什么我不能在测试用例中正确捕获异常?如何正确检查是否抛出了异常,以便可以通过测试?

1 个答案:

答案 0 :(得分:1)

您需要传递一个函数句柄来验证错误。现在发生的事情是您正在调用this.verifyError(options.setHostname(hostName), 'WTrade:invalidParameter');,它实际上是通过一个输出参数调用options.setHostname(hostName)并将其作为参数传递给verifyError。相反,它应该是:

this.verifyError(@() options.setHostname(hostName), 'WTrade:invalidParameter');

此外,我建议使用标准属性Hostname,而不是使用验证语法来编写setter方法,如下所示:

classdef PostgreSQLConnectionOptions < handle

  properties 
    Hostname(1,1) string = "";
  end

end

不是,如果您需要执行更多自定义验证,则可以始终像这样编写setter方法:

methods
    function set.Hostname(options, hostname)
        % some additional validation here
    end
end

请注意,尽管在使用属性时,要使用verifyError,您需要将其包装在函数中:

classdef PostgreSQLConnectionOptionsTest < matlab.unittest.TestCase

  methods (Test)

    function testWrongHostnameArray(this)
      options = WTrade.Database.PostgreSQLConnectionOptions();
      hostName = ["h1" "h2"];
      this.verifyError(@setHostname, 'WTrade:invalidParameter');
      function setHostname
          options.Hostname = hostname;
      end
    end

  end
end

即使您需要将此属性包装在测试函数中,但按原样使用属性通常还是更好的体验。我们有built in encapsulation with matlab,我认为最好利用它。