Class Substitution in Mocking Framework

8 views (last 30 days)
Alex
Alex on 16 Jul 2025
Answered: Meet on 9 Sep 2025
I'm having an issue understanding some of the unit test mocking framework. This is for Matlab 2020b.
Currently I have class based unit testing setup for this project. I have previously used mock's to replace user input and UI interactions.
However the current limited mock interactions work by passing the mocked class as an arguement which would not be appropriate for the next set of tests, and I need help understanding how to do the following:
I am writing tests for the class of DataTable, which will in turn create objects of the class DataFile.
Simplified:
classdef DataTable
properties
files
end
methods (Access = public)
function dataTable = DataTable(varargin)
%standard constructor
% [...]
end
function dataTable = import(dataTable, target)
% [...]
newfile = DataFile(target)
newfile = newfile.import(target)
dataTable.files = [dataTable.files,newfile]
end
end
end
classdef DataFile
properties
filename
data
end
methods
function file = DataFile(target)
arguments
target = ''
end
file.filename = target(find((target == '\'),1,'last')+1:end);
%Some other standard constructor setup that i've ommitted.
%[...]
end
function file = import(file, target)
%file.data = x %code that loads data from target file
end
end
end
I'm attempting to create a mockDataFile with a mocked method mockDataFile.import which will null out the import step since the contents of the file are irrelevant to the testing of the DataTable.
The issue i'm running into is that all the examples I can find of this sort of interaction would pass the mock as an arguement, in the format:
dataTable = DataTable(mockDataFile)
however this is not acceptable in my test case, as there is no point at which during normal operation where I can do a dependency injection like this without adding test specific code which would bring more important validations into question.
So i'm trying to understand how to have DataTable create a fake DataFile when it creates those objects, my initial version was this:
classdef DataTableTest < matlab.unittest.TestCase & matlab.mock.TestCase
properties
dataTable
dataMock
mockDataBehavior
end
methods (TestClassSetup)
function setup(testCase)
import matlab.mock.actions.AssignOutputs;
import matlab.mock.constraints.WasCalled
[testCase.dataMock,testCase.mockDataBehavior] = testCase.createMock(?DataFile,"MockedMethods",["import"]);
when(withAnyInputs(testCase.mockDataBehavior.import),AssignOutputs([]));
end
end
methods (Test)
function testMockData(testCase)
file = 'a test file'
path = 'the/test/path/'
target = append(path,file)
testCase.dataTable = DataTable();
testCase.table = testCase.table.import(target);
%At this point the current test has incorrectly imported the
%real data, as it uses the real DataFile and not the Mock.
%So the test does complete as a success, but its wasted time
%and memory on doing the import of the real files.
testCase.verifyEqual(testCase.dataTable.files(1).filename,file) %etc
end
end
end
I was able to fake the behavior by making a copy of the DataFile class with the import section commented out, but that is also not a valid verification because its not scritpable in the same project framework. The other thing I was imagining was some way to tell the test class that it is in an alias'd working directory where the fake DataFile class file lives so that it would call that instead of the real one.
I hope to understand how to do this, or if i'm approaching it from the wrong direciton and if so what I should be doing instead.
Of course, my issue isn't that my testing is failing, its that the import functions have their own whole test sequence, and as the tests at the table level increase in complexity the sequence starts spending a lot of time doing the whole import on the test files, which is what i'm trying to cut out.

Answers (1)

Meet
Meet on 9 Sep 2025
Hi Alex,
You can try the following workarounds to avoid slow imports:
  1. Temporary 'Fake Class' Using MATLAB Path Tricks:
  • Create a new "DataFile.m" file in a separate test folder. In it, you leave out or disable the "import" method.
  • In your test file, temporarily add that test folder to MATLAB's path before running your test, using "PathFixture". MATLAB will then use the fake "DataFile" instead of the real one when constructing objects inside "DataTable".
2. Allow Optional 'Fake' DataFile via Constructor
  • Add an optional parameter in the "DataTable" constructor to accept a "creator" or prototype for "DataFile". By default, it works just like before.
  • When writing your test, you provide a lightweight fake object or factory that has an "import" method that does nothing.
I hope this helps!

Products


Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!