Please ensure Javascript is enabled for purposes of website accessibility
Powered by Zoomin Software. For more details please contactZoomin

AVEVA™ Integration Service

Testing

  • Last UpdatedJul 28, 2026
  • 4 minute read

This section covers unit testing strategies and patterns for applications using the AVEVA Integration Service Data API SDK.

Test Setup

Test Project Structure

Required Test Packages

<!-- In your test .csproj -->

<ItemGroup>

<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.x" />

<PackageReference Include="xunit" Version="2.x" />

<PackageReference Include="xunit.runner.visualstudio" Version="2.x" />

<PackageReference Include="Moq" Version="4.x" />

<PackageReference Include="AutoFixture" Version="4.x" />

<PackageReference Include="FluentAssertions" Version="6.x" />

</ItemGroup>

Mocking the SDK

Mock HttpClient

using Moq;

using Moq.Protected;

[Fact]

public async Task GetDataSources_WithValidHost_ReturnsDataSources()

{

// Arrange

var datasources = new List<DatasourceDto>

{

new DatasourceDto { Name = "Eng1", Type = "Engineering" }

};

var mockHandler = new Mock<HttpMessageHandler>();

mockHandler

.Protected()

.Setup<Task<HttpResponseMessage>>(

"SendAsync",

ItExpr.IsAny<HttpRequestMessage>(),

ItExpr.IsAny<CancellationToken>()

)

.ReturnsAsync(new HttpResponseMessage

{

StatusCode = HttpStatusCode.OK,

Content = new StringContent(

JsonConvert.SerializeObject(datasources),

Encoding.UTF8,

"application/json")

});

var httpClient = new HttpClient(mockHandler.Object);

// Act

var client = DataApiClientFactory.CreateDataApiClient<EngineeringClient>(host);

var result = await client.GetDataSources("");

// Assert

Assert.NotNull(result);

Assert.Single(result);

Assert.Equal("Eng1", result.First().Name);

}

Mock HubConnectionManager

[Fact]

public async Task Subscribe_WithValidTopic_Succeeds()

{

// Arrange

var mockHubConnection = new Mock<IHubConnection>();

mockHubConnection.Setup(x => x.ConnectionId).Returns("test-connection-id");

mockHubConnection.Setup(x => x.State).Returns(HubConnectionState.Connected);

var mockHubManager = new Mock<IHubConnectionManager>();

mockHubManager

.Setup(x => x.CreateHubConnectionAsync(

It.IsAny<AuthenticationType>(),

It.IsAny<string>(),

It.IsAny<CancellationTokenSource>(),

It.IsAny<string>()))

.ReturnsAsync(mockHubConnection.Object);

// Act

var pubSubClient = new SignalRPubSubClient(mockHubManager.Object, host);

var result = await pubSubClient.Subscribe("TestTopic");

// Assert

Assert.NotNull(result);

}

Base Test Class with Mock Helpers

public abstract class BaseDataApiClientTests

{

protected Mock<IIntegrationHttpClientFactory> mockHttpClientFactory;

protected Mock<IHubConnectionManager> mockHubConnectionManager;

protected Mock<HttpMessageHandler> handlerMock;

protected BaseDataApiClientTests()

{

handlerMock = new Mock<HttpMessageHandler>();

var httpClient = new HttpClient(handlerMock.Object);

mockHttpClientFactory = new Mock<IIntegrationHttpClientFactory>();

mockHttpClientFactory

.Setup(x => x.CreateClient(It.IsAny<string>()))

.Returns(httpClient);

mockHubConnectionManager = new Mock<IHubConnectionManager>();

}

protected void SetupHttpResponse<T>(T data) where T : class

{

handlerMock

.Protected()

.Setup<Task<HttpResponseMessage>>(

"SendAsync",

ItExpr.IsAny<HttpRequestMessage>(),

ItExpr.IsAny<CancellationToken>())

.ReturnsAsync(new HttpResponseMessage

{

StatusCode = HttpStatusCode.OK,

Content = new StringContent(

JsonConvert.SerializeObject(data),

Encoding.UTF8,

"application/json")

});

}

}

Unit Test Examples

Test Data Retrieval

[Fact]

public async Task GetDataSources_ReturnsAllDataSources()

{

// Arrange

var expectedDatasources = new List<DatasourceDto>

{

new DatasourceDto { Name = "DS1", Type = "Engineering" },

new DatasourceDto { Name = "DS2", Type = "Excel" }

};

SetupHttpResponse(expectedDatasources);

var client = new EngineeringClient(

mockHttpClientFactory.Object,

mockHubConnectionManager.Object,

host);

// Act

var result = await client.GetDataSources("");

// Assert

result.Should().HaveCount(2);

result.Should().Contain(x => x.Name == "DS1");

}

Test Exception Handling

[Fact]

public async Task GetDataSources_OnTimeout_ThrowsTimeoutException()

{

// Arrange

handlerMock

.Protected()

.Setup<Task<HttpResponseMessage>>(

"SendAsync",

ItExpr.IsAny<HttpRequestMessage>(),

ItExpr.IsAny<CancellationToken>())

.ThrowsAsync(new TimeoutException("Connection timed out"));

var client = new EngineeringClient(

mockHttpClientFactory.Object,

mockHubConnectionManager.Object,

host);

// Act & Assert

await Assert.ThrowsAsync<TimeoutException>(

async () => await client.GetDataSources(""));

}

Test Pub/Sub Operations

[Fact]

public async Task Publish_WithValidMessage_PublishesSuccessfully()

{

// Arrange

var mockHubConnection = new Mock<IHubConnection>();

mockHubConnection

.Setup(x => x.InvokeAsync(It.IsAny<string>(), It.IsAny<object[]>()))

.Returns(Task.CompletedTask);

var mockHubManager = new Mock<IHubConnectionManager>();

mockHubManager

.Setup(x => x.CreateHubConnectionAsync(

It.IsAny<AuthenticationType>(),

It.IsAny<string>(),

It.IsAny<CancellationTokenSource>(),

It.IsAny<string>()))

.ReturnsAsync(mockHubConnection.Object);

var pubSubClient = new SignalRPubSubClient(mockHubManager.Object, host);

var message = new Broadcast

{

PublisherConnectionId = "conn1",

CreatedTime = DateTime.UtcNow,

User = "testuser",

Context = "Test message"

};

// Act

var result = await pubSubClient.Publish(message, host, "TestTopic");

// Assert

Assert.NotNull(result);

}

Parameterized Tests

[Theory]

[InlineData("")]

[InlineData("Status eq 1")]

[InlineData("Modified gt datetime'2024-01-01'")]

public async Task GetTableData_WithVariousFilters_ReturnsData(string filter)

{

// Arrange

var expectedData = new List<TableData> { new TableData { Name = "Row1" } };

SetupHttpResponse(expectedData);

var client = new EngineeringClient(

mockHttpClientFactory.Object,

mockHubConnectionManager.Object,

host);

// Act

var result = await client.GetTableData("DS", "Table", filter);

// Assert

result.Should().NotBeEmpty();

}

Integration Tests

Test with Real DataAPI

public class DataApiIntegrationTests : IAsyncLifetime

{

private readonly string _host;

private EngineeringClient _client;

public DataApiIntegrationTests()

{

_host = "https://your-test-ais-server/api/v1/datasources";

}

public async Task InitializeAsync()

{

_client = DataApiClientFactory.CreateDataApiClient<EngineeringClient>(_host);

}

public Task DisposeAsync() => Task.CompletedTask;

[Fact]

[Trait("Category", "Integration")]

public async Task RetrievesDataFromRealAPI()

{

var dataSources = await _client.GetDataSources("");

Assert.NotNull(dataSources);

}

}

Test Configuration Loading

[Fact]

public void CreateClient_WithConfigFile_LoadsConfigurationCorrectly()

{

var host = ConfigurationManager.AppSettings["host"];

var authType = AuthenticationType.NTLM;

var client = DataApiClientFactory.CreateDataApiClient<EngineeringClient>(host, authType);

Assert.NotNull(client);

}

Test Data

Creating Test Fixtures

public class DataSourceFixture

{

public static DatasourceDto CreateDatasource(

string name = "TestDS",

string type = "Engineering") => new DatasourceDto

{

Name = name,

Type = type,

Description = $"Test data source: {name}"

};

public static IEnumerable<DatasourceDto> CreateMultipleDatasources(int count = 3)

{

for (int i = 1; i <= count; i++)

yield return CreateDatasource($"DS{i}", "Engineering");

}

}

Using AutoFixture

[Fact]

public void CreateRandomDataSources()

{

var fixture = new Fixture();

var datasources = fixture.CreateMany<DatasourceDto>(5);

Assert.Equal(5, datasources.Count());

}

Running Tests

.NET CLI

# Run all tests

dotnet test

# Run specific test class

dotnet test --filter "ClassName=EngineeringClientTest"

# Run specific test method

dotnet test --filter "MethodName=GetDataSources_ReturnsData"

# Verbose output

dotnet test --verbosity normal

# Release configuration

dotnet test -c Release

Visual Studio Test Explorer

  1. Open Test → Test Explorer (Ctrl+E, T)

  2. Click Run All Tests or select individual tests

  3. View pass/fail results in the panel

Continuous Integration (GitHub Actions)

name: Tests

on: [push, pull_request]

jobs:

test:

runs-on: windows-latest

steps:

- uses: actions/checkout@v3

- uses: actions/setup-dotnet@v3

with:

dotnet-version: '8.0.x'

- run: dotnet test --verbosity normal

Code Coverage

Generate Coverage Report

# One-time tool install

dotnet tool install -g dotnet-coverage

# Collect coverage

dotnet-coverage collect -f cobertura -o coverage.cobertura.xml dotnet test

# Generate HTML report (requires ReportGenerator)

dotnet tool install -g reportgenerator

reportgenerator -reports:coverage.cobertura.xml -targetdir:coveragereport

Coverage Targets

  • Unit test coverage: 80%+

  • Critical data paths: 95%+

  • Infrastructure/boilerplate: lower coverage acceptable

public class EngineeringClientTests

{

private readonly Mock<IIntegrationHttpClientFactory> _mockHttpClientFactory;

private readonly Mock<IHubConnectionManager> _mockHubManager;

private readonly EngineeringClient _client;

public EngineeringClientTests()

{

_mockHttpClientFactory = new Mock<IIntegrationHttpClientFactory>();

_mockHubManager = new Mock<IHubConnectionManager>();

_client = new EngineeringClient(

_mockHttpClientFactory.Object,

_mockHubManager.Object,

"http://test");

}

#region GetDataSources Tests

[Fact]

public async Task GetDataSources_WithEmptyFilter_ReturnsAllDataSources()

{

// Arrange – setup mock response

// Act

var result = await _client.GetDataSources("");

// Assert

Assert.NotNull(result);

}

[Fact]

public async Task GetDataSources_OnConnectionError_ThrowsHubConnectionInitializationException()

{

// Arrange – configure mock to throw

// Act & Assert

await Assert.ThrowsAsync<HubConnectionInitializationException>(

() => _client.GetDataSources(""));

}

#endregion

#region GetTableData Tests

[Theory]

[InlineData("")]

[InlineData("filter")]

public async Task GetTableData_WithVariousFilters_ReturnsExpectedData(string filter)

{

// Test implementation

}

#endregion

}

In This Topic
Related Links