Write unit tests for scripts
From version 1.1.0 and later, the Sitecore Content Hub CLI lets you write and execute unit tests for your scripts using xUnit.net and NSubstitute.
When using [Theory]
, [InlineData]
is currently the only way of providing arguments to the test method.
This walkthrough describes how to:
Create a script
In your working directory, create a script with the name MyScript.csx
:
#load "./references/Action.csx"
/**------------ Include above to support intellisense on Content Hub types in editor ----------------**/
// Script Start
var entity = Context.Target as IEntity;
if (entity == null)
{
MClient.Logger.Error("Entity is null.");
}
Create a test script
Unit test scripts are located in the unit-tests
directory within the working directory and are expected to be named after the script that they are testing (for example, MyScript.csx
). For that reason, it is important to have one test script for each script.
In the unit-tests
directory, create a script matching the name of the script to test:
#load "../references/UnitTest.csx"
/**------------ Include above to support intellisense on Content Hub types in editor ----------------**/
// Script Start
using System.Threading.Tasks;
using NSubstitute;
using Xunit;
[Fact]
public async Task Should_Log_Error_If_Entity_Is_Null()
{
// Arrange
var client = Substitute.For <IMClient>();
var context = Substitute.For <IActionScriptContext>();
context.Target.Returns(null);
// Act
await ScriptRunner.ExecuteAsync(client, context);
// Assert
client.Logger.Received(1).Error("Entity is null.");
}
The file structure should now be the following:
[working folder]
├── lib
│ └── ...
├── references
│ ├── UnitTest.csx
│ └── ...
├── unit-tests
│ └── MyScript.csx <-- test script with the same name
├── MyScript.csx
├── omnisharp.json
├── references.json
Explanation of the test script code
-
Create a named test method. The
[Fact]
attribute tells the test runner that this method is a unit test:RequestResponse[Fact] public async Task Should_Log_Error_If_Entity_Is_Null()
-
Create mocks of the required objects that will be passed down to the actual script. This sets the context for different scenarios as well as mimic API calls that are being done through the
MClient
instance within the script. In this example, theTarget
property of the context is explicitly set tonull
:RequestResponsevar client = Substitute.For <IMClient>(); var context = Substitute.For <IActionScriptContext>(); context.Target.Returns(null);
-
Compiles and executes the related script (based on the file name) and passes the
client
andcontext
instances down. When following the commonly used AAA (Arrange - Act - Assert) pattern, this call would be the Act section:RequestResponseawait ScriptRunner.ExecuteAsync(client, context);
-
Verify that the conditions of the test are met. In this case, an error message should have been logged.
RequestResponseclient.Logger.Received(1).Error("Entity is null.");
Run unit tests
You can either run all unit tests at once, or you can run a single unit test:
-
To run all unit tests, use the following code:
RequestResponsech-cli scripting unit-test (--folder <PATH_TO_WORKING_DIRECTORY> )
-
To run a single unit test, use the following code:
RequestResponsech-cli scripting unit-test (--<FOLDER_PATH_TO_WORKING_DIRECTORY> ) --name <TEST_FILE> Example: ch-cli scripting unit-test --name <TEST_FILE>