Skip to content

Testing

You can test your plugin without starting HydroSym using the PluginTestHost class from the SDK or the HydroSymPluginTester CLI tool.

Unit testing with PluginTestHost

PluginTestHost drives your plugin class directly — no DLL loading, no JSON serialization — making it fast and debuggable.

Add the test package:

dotnet add package PARO.HydroSym.PluginSDK.Testing
dotnet add package xunit

Basic test structure

using PARO.HydroSym.PluginSDK.Testing;
using Xunit;

public class AcmeErpPluginTests : IDisposable
{
    private readonly PluginTestHost _host;

    public AcmeErpPluginTests()
    {
        _host = new PluginTestHost(new AcmeErpPlugin());
        _host.Initialize(new InitializeRequest
        {
            HydroSymVersion = "2025.55.0.0",
            ConfigPath = "testdata/acme-test.ini",
            HydroSymDataPath = "C:\\ProgramData\\HydroSym",
            MainWindowHandle = 0,
            WindowsUser = "testuser",
        });
    }

    public void Dispose() => _host.Finalize_();
}

Testing GetInfo

[Fact]
public void GetInfo_ReturnsCorrectApiVersion()
{
    var info = _host.GetInfo();

    Assert.Equal(1, info.ApiVersion);
    Assert.Contains("getComponentParameters", info.Capabilities);
}

[Fact]
public void GetInfo_HasSearchMenuItem()
{
    var info = _host.GetInfo();
    var searchItem = info.Menus?.FirstOrDefault(m => m.Id == "acme-search");

    Assert.NotNull(searchItem);
    Assert.Equal("component", searchItem!.ResultType);
}

Testing GetComponentParameters

[Fact]
public void GetComponentParameters_KnownValve_ReturnsReleasedStatus()
{
    var response = _host.GetComponentParameters(new GetComponentParametersRequest
    {
        ArticleCode = "HV-301",
    });

    Assert.Equal("HV-301", response.ArticleCode);
    Assert.Equal("released", response.Status);
    Assert.Equal("EUR", response.Currency);
    Assert.True(response.Price > 0);
}

[Fact]
public void GetComponentParameters_UnknownCode_ThrowsPluginException()
{
    var ex = Assert.Throws<PluginException>(() =>
        _host.GetComponentParameters(new GetComponentParametersRequest
        {
            ArticleCode = "UNKNOWN-999",
        }));

    Assert.Equal("NOT_FOUND", ex.ErrorCode);
}

Testing menu actions with a mock context

[Fact]
public void GetMenuItemState_NoOpenProject_DisablesCheckinButton()
{
    var response = _host.GetMenuItemState(new GetMenuItemStateRequest
    {
        MenuItemIds = ["acme-checkin"],
        Context = new PluginContext
        {
            ProjectPath = null,   // no project open
        },
    });

    Assert.False(response.States["acme-checkin"].Enabled);
}

Verifying JSON round-trips

The SDK includes helpers to verify that your response objects serialize correctly to the JSON the transport layer will send:

[Fact]
public void GetComponentParameters_ResponseSerializesCorrectly()
{
    var response = _host.GetComponentParameters(new GetComponentParametersRequest
    {
        ArticleCode = "RV-101",
    });

    // Verify no serialization exceptions and round-trip fidelity
    var json = PluginSerializer.Serialize(response);
    var roundTripped = PluginSerializer.Deserialize<GetComponentParametersResponse>(json);

    Assert.Equal(response.ArticleCode, roundTripped.ArticleCode);
    Assert.Equal(response.Status, roundTripped.Status);
}

CLI testing with HydroSymPluginTester

HydroSymPluginTester.exe is a command-line tool that loads your native DLL and calls methods against it, displaying the raw JSON exchange. Use it to verify the built DLL behaves correctly before deploying.

# List all supported methods
HydroSymPluginTester.exe --dll AcmeErpPlugin.dll --call GetInfo

# Call GetComponentParameters
HydroSymPluginTester.exe --dll AcmeErpPlugin.dll --call GetComponentParameters \
    --request "{\"articleCode\": \"HV-301\"}"

# Run all methods from a test script
HydroSymPluginTester.exe --dll AcmeErpPlugin.dll --script testcases.json

Test script format

[
  {
    "method": "GetInfo",
    "request": {},
    "expect": { "apiVersion": 1 }
  },
  {
    "method": "GetComponentParameters",
    "request": { "articleCode": "HV-301" },
    "expect": { "status": "released", "currency": "EUR" }
  },
  {
    "method": "GetComponentParameters",
    "request": { "articleCode": "UNKNOWN-999" },
    "expectError": { "code": "NOT_FOUND" }
  }
]

The tester exits with code 0 if all assertions pass, 1 otherwise — suitable for use in CI pipelines.

CI integration

# .github/workflows/test.yml
- name: Build plugin
  run: dotnet publish -c Release

- name: Run unit tests
  run: dotnet test

- name: Run integration tests
  run: |
    HydroSymPluginTester.exe \
      --dll bin/Release/net8.0/win-x64/publish/AcmeErpPlugin.dll \
      --script tests/integration/testcases.json