sap-commerce-tests
Write or review SAP Commerce unit tests (JUnit 4 + Mockito) that follow project conventions, and run a single test with JaCoCo coverage via Ant. Use when creating, updating, or reviewing SAP Commerce unit test classes or when asked to run a single test with coverage.
npx skills add commerce-cloud-integrations/sap-commerce-agent-skills --skill sap-commerce-testsSAP Commerce Unit Tests
Overview
Create or update SAP Commerce unit tests that follow project conventions. When tests are created or changed, run a single test with coverage and report results.
When to Use
- Writing new SAP Commerce unit tests (JUnit 4 + Mockito).
- Updating existing unit tests for SAP Commerce.
- Running a single test with coverage and reporting JUnit + JaCoCo results.
Workflow
- Locate or create the test class in the extension
testsrcpath. - Follow naming, structure, and mocking rules in this document.
- Register the test in the extension
*-testclasses.xmlif required by the project. - Run the single test with coverage using
scripts/run_single_test_with_coverage.sh. - Summarize JUnit results and coverage (extension + class) in the response.
Test Method Structure (Arrange-Act-Assert)
Use clear section comments.
@Test
public void methodName_scenario_expectedBehavior() {
// Arrange
// Act
// Assert
}
Naming Convention
Use methodName_scenario_expectedBehavior for all test methods.
Examples:
@Test
public void checkReorderability_WhenOrderIsCancelled_ShouldReturnFalse() { }
@Test
public void populate_WithNullSource_ShouldThrowIllegalArgumentException() { }
@Test
public void calculateDiscount_WhenCustomerIsVip_ShouldApply20PercentDiscount() { }
@Test(expected = EmptyCartException.class)
public void validateCart_WhenCartIsEmpty_ShouldThrowEmptyCartException() { }
Test Class Structure
Default to JUnit 4 with MockitoJUnitRunner.
@UnitTest
@RunWith(MockitoJUnitRunner.class)
public class DefaultPmiOrderServiceTest {
@InjectMocks
private DefaultPmiOrderService service;
@Mock
private DependencyService dependencyService;
@Before
public void setUp() {
// Common setup for all tests
}
@Test
public void methodName_scenario_expectedBehavior() {
// Test implementation
}
}
Key Rules
- Use real objects for DTOs; do not mock DTOs.
- Mock only services and dependencies with behavior.
- Test exactly one scenario per test with clear assertions.
- Use descriptive assertion messages to explain failures.
- Keep tests independent; avoid shared state between tests.
- Use
@RunWith(MockitoJUnitRunner.class)to detect unused mocks. - Never test constructors or bean injections.
- Use Mockito
doThrow().when(...)for void exceptions when needed. - Never use
MockedStatic, and never mock any Utils class behavior.
Required Follow-up After Creating Tests
After creating or updating tests, run the tests with coverage and include a concise summary:
- JUnit results: tests, failures, errors, time, and the report path.
- Coverage (extension report): instructions, branches, lines, methods, classes.
- Coverage (single-class report): instructions, branches, lines, methods, classes.
- Paths to the HTML reports.
If tests or coverage fail, say so clearly and include the failure reason from the test report.
Run Single Test with Coverage
Use the provided script (run from repo root):
./skills/sap-commerce-tests/scripts/run_single_test_with_coverage.sh \
--extension <extensionname> \
--test-class <fully.qualified.TestClass> \
--target-class <fully.qualified.ProdClass> \
[--ext-path <extension-path>]
Outputs:
- Extension report:
/tmp/jacoco/report-extension/index.html - Class report:
/tmp/jacoco/report-class/index.html
Troubleshooting
- If you see JDWP transport errors, ensure the debug agent is stripped from
standalone.javaoptions(the script filters it). - If you still see "junit slave tenant" errors, ensure
-Dtestclasses.suppress.junit.tenant=trueis present. - If
antis not found, ensurehybris/bin/platform/setantenv.shis sourced by the script. - If tests fail with "Could not initialize plugin: interface org.mockito.plugins.MockMaker" on SAP JVMs, ensure the Byte Buddy agent is present (the script adds it automatically if found).