Michael A
Michael A

Reputation: 4615

How do I use MATLAB's unit testing framework to test the number of output arguments (nargout)?

I have a method in a custom class that can only return 0, 1, or 2 outputs. I check this with nargoutchk(0, 2). I'm at a loss when it comes to unit testing this method when a wrong number of output arguments are specified. This doesn't work:

classdef MyClassTest < matlab.unittest.TestCase
    methods (Test)
        function testMyMethod(testCase)
            verifyError(testCase, @() [x, y, z] = myMethod(5), 'MATLAB:nargoutchk:tooManyOutputs')
        end
    end

    methods
        function varargout = myMethod(a)
            nargoutchk(0, 2)
        end
    end
end

because MATLAB can't perform assignments inside an anonymous function. This doesn't work either:

classdef MyClassTest < matlab.unittest.TestCase
    methods (Test)
        function testMyMethod(testCase)
            try
                [x, y, z] = myMethod(5);
            catch ex
                verifyError(testCase, @() rethrow(ex), 'MATLAB:nargoutchk:tooManyOutputs')
            end
        end
    end

    methods
        function varargout = myMethod(a)
            nargoutchk(0, 2)
        end
    end
end

because rethrow isn't recognized inside an anonymous function (because it's not in the immediate scope of the catch block).

Are there any workarounds for this, or is it not possible in MATLAB?

Upvotes: 1

Views: 525

Answers (1)

Andy Campbell
Andy Campbell

Reputation: 2187

You can do this easily using the Throws constraint and verifyThat instead of verifyError. This can look like this:

classdef MyClassTest < matlab.unittest.TestCase
    methods (Test)
        function testMyMethod(testCase)
            import matlab.unittest.constraints.Throws;

            testCase.verifyThat(@() myMethod(5), ...
                Throws('MATLAB:nargoutchk:tooManyOutputs', 'WhenNargoutIs', 3));
        end
    end
end

Check out the Throws documentation for more info.

Another alternative is to wrap the function call you pass to verifyError into a nested or local function:

classdef MyClassTest < matlab.unittest.TestCase
    methods (Test)
        function testMyMethod(testCase)
            verifyError(testCase, @callMyMethodWithThreeOutputs, ...
                'MATLAB:nargoutchk:tooManyOutputs');
        end
    end
end

function callMyMethodWithThreeOutputs
[~,~,~] = myMethod(5);
end

Hope that helps!

Upvotes: 4

Related Questions