Contenido principal

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:

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 polyspaceroot\polyspace\examples\doc_pstest\mock_variables\src. Here, polyspaceroot is the Polyspace installation folder, for instance, C:\Program Files\Polyspace\R2026a. To continue with this tutorial:

  1. Create a new Polyspace Platform project and add the folder to the project.

  2. 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++;
    }
}
With the types defined in a header 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);
#endif
Suppose that you do not want to invoke the readData() 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:

  1. On the Projects pane, right-click the function readData and select Create Mock.

  2. Enter the following mock definition and click Apply to save the mock. Here, path\to\decls.h is the full path to the header file decls.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 statusMockVar that you can use to choose a mock implementation. For instance, if you set the value of statusMockVar to R_SUCCESS in a test, the mock implementation returns the value R_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;
}
This return value ensures that the caller function 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:

  1. On the Projects pane, right-click the updateState function and select Add Test Case.

  2. In the Inputs section of the test, right-click the row for the input stateVariable and 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: 0

    • updateCount: 0

  3. In the Assessments section of the test, right-click the row for the assessment on stateVariable and 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: 1

    • updateCount: 1

  4. In the Callees section of the test, right-click the function readData and select the mock readData_mock. You now have access to the variable statusMockVar that is exported from this mock.

  5. In the Inputs section of the test, click the Add inputs button:

    1. Select the mock variable statusMockVar to enter a new row for the mock variable in the Inputs section of the test.

    2. 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;
}
This return value ensures that the function 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:

  1. On the Projects pane, right-click the previously created test and select Duplicate Test.

  2. 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: 0

      • updateCount: 0

    • In the Inputs section of the test, change the value of the input statusMockVar to R_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);
#endif

Update 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:

  1. Open the test case document.

  2. Right-click the step node in the left side of the test case editor and select Update Code Under Test.

  3. 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 *).

  4. In the Remapping Code Under Test dialog box, keep the existing mapping, and select OK.

  5. 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.

See Also

Topics