Change Mock or Stub Implementation Based on Test
When authoring a unit test for a C/C++ function in the Polyspace® Platform user interface, you can replace a callee of the function with an alternative definition using one of these ways:
Write a stub to replace an undefined callee.
See Test Functions with Undefined Callees in Polyspace Platform User Interface.
Write a mock to override a callee that is already defined.
See Override Callee Definitions When Testing Functions in Polyspace Platform User Interface.
This topic shows how to define a single stub or mock that has a different implementation in different tests.
Example Files
This tutorial uses the files in the folder
.
Here, polyspaceroot\polyspace\examples\doc_pstest\mock_variables\src is the Polyspace installation folder, for instance, polyspacerootC:\Program
Files\Polyspace\R2026a. To continue with this tutorial:
Create a new Polyspace Platform project and add the folder to the project.
Select Parse Code on the toolstrip to analyze the files in the folder.
Suppose you have to test the function updateState():
#include "decls.h"
enum readStatus readData(void) {
//readData() implementation
}
void updateState(struct State* stateVariable) {
enum readStatus status = readData();
if (status == R_SUCCESS) {
stateVariable->indicator = 1;
stateVariable->updateCount++;
}
}decls.h:#ifndef DECLS_H
#define DECLS_H
enum readStatus {
R_SUCCESS,
R_FAILURE
};
struct State {
int indicator;
int updateCount;
};
enum readStatus readData(void);
void updateState(struct State* stateVariable);
#endifreadData() function in your test but invoke a mock function instead. You can write a single mock that returns one of the two possible enum values R_SUCCESS and R_FAILURE. In your test, you can choose which enum value to return.Define Mock
Define a mock for the readData() function:
On the Projects pane, right-click the function
readDataand select Create Mock.Enter the following mock definition and click Apply to save the mock. Here,
path\to\decls.his the full path to the header filedecls.h. The inclusion of this header is prefilled in the Header section of the mock and can be copied over into the Exported declarations section.Exported declarations:
#include "path\to\decls.h" extern enum readStatus statusMockVar;Header:
#include "path\to\decls.h" enum readStatus statusMockVar;Body of mock
readData_mock:return statusMockVar;
When you apply the mock, this mock definition exports a global variable
statusMockVarthat you can use to choose a mock implementation. For instance, if you set the value ofstatusMockVartoR_SUCCESSin a test, the mock implementation returns the valueR_SUCCESS.
Apply Mock
Define two tests that use a different implementation of your mock function.
Apply Mock Implementation That Returns Success Status
In the first test, you will apply the mock in a way such that the mock body has the definition:
enum readStatus readData(void) {
return R_SUCCESS;
}updateState() goes through the block controlled by if (status == R_SUCCESS) and updates the variable stateVariable:void updateState(struct State* stateVariable) {
enum readStatus status = readData();
if (status == R_SUCCESS) {
stateVariable->indicator = 1;
stateVariable->updateCount++;
}
}To write a test for the function updateState() that defines this mock implementation:
On the Projects pane, right-click the
updateStatefunction and select Add Test Case.In the Inputs section of the test, right-click the row for the input
stateVariableand select Add Pointer Target. Leave the default name and size of the pointer target.After creating the target, in the Test Data section above the step, expand the node for the target. You can see these default values:
indicator: 0updateCount: 0
In the Assessments section of the test, right-click the row for the assessment on
stateVariableand select Add Pointer Target. Leave the default name and size of the pointer target.After creating the target, in the Test Data section above the step, expand the node for the assessment target and set these values:
indicator: 1updateCount: 1
In the Callees section of the test, right-click the function
readDataand select the mockreadData_mock. You now have access to the variablestatusMockVarthat is exported from this mock.In the Inputs section of the test, click the
button:Select the mock variable
statusMockVarto enter a new row for the mock variable in the Inputs section of the test.Set the value of this variable to
R_SUCCESS.
When you build and run the test, you see passing test results.
Apply Mock Implementation That Returns Failure Status
In the second test, you will apply the mock in a way such that the mock body has the definition:
enum readStatus readData(void) {
return R_FAILURE;
}updateState() bypasses the block controlled by if (status == R_SUCCESS) and retains the old values of stateVariable:void updateState(struct State* stateVariable) {
enum readStatus status = readData();
if (status == R_SUCCESS) {
stateVariable->indicator = 1;
stateVariable->updateCount++;
}
}To write a test for the function updateState() that defines this mock implementation:
On the Projects pane, right-click the previously created test and select Duplicate Test.
In the new test case, make the following changes:
In the Test Data section of the test, change the pointer target for the assessment as follows:
indicator: 0updateCount: 0
In the Inputs section of the test, change the value of the input
statusMockVartoR_FAILURE.
When you build and run the test, you see passing test results.
Modify Source Code
Suppose that you need to change the possible readStatus enum
values defined in the decls.h header file. Instead of just
R_SUCCESS and R_FAILURE, you need a third
value,
R_UNKNOWN.
#ifndef DECLS_H
#define DECLS_H
enum readStatus {
R_SUCCESS,
R_FAILURE,
R_UNKNOWN
};
struct State {
int indicator;
int updateCount;
};
enum readStatus readData(void);
void updateState(struct State* stateVariable);
#endifUpdate Existing Mock and Tests
Existing mocks and tests do not automatically pick up changes to mock variables when you modify your source code. After making changes, you need to refresh your mocks and update any test steps that use the modified mock variables. These actions will reparse your source code and make any necessary updates to your mocks and test steps.
Update Mock
To update the mock you created, find your project in the Projects pane, right-click on the Mocks node, and select Refresh. This action updates all mocks in the project. If you create a new graphical test case and replace a callee of the function under test with a mock, the mock will have the latest mock variable definitions. For more information about working with mocks, see Override Callee Definitions When Testing Functions in Polyspace Platform User Interface.
Update Tests
Updating the mocks ensures that your mock variables are in sync with your source code for authoring new graphical tests. To update mock variables in your existing graphical tests, you need to update each test step that uses the mock variable. For each of the two test steps you created, follow these steps:
Open the test case document.
Right-click the step node in the left side of the test case editor and select Update Code Under Test.
In the Update Code Under Test dialog box, select the Replace function with radio button and choose the current code under test,
updateState(struct State *).In the Remapping Code Under Test dialog box, keep the existing mapping, and select OK.
In the test case document, scroll to the Inputs section and expand the Value drop down for
statusMockVar. The mock variable values have been updated, and you can now see the new value,R_UNKNOWN, in the list.
For more information about updating existing tests, see Update Tests in Polyspace Platform User Interface.