英文:
How to properly mock client.Publish.GetAsync(request) in Aquarius SDK unit test?
问题
以下是翻译好的代码部分:
我在名为 AquariusService 的类中编写了下面的方法,该方法被称为 Aquarius SDK:
public async Task<TimeAlignedDataServiceResponse> GetTimeSeriesPointsAsync(IAquariusClient client,
List<Guid> timeSeriesId,
DateTimeOffset? fromDate,
DateTimeOffset? toDate)
{
var request = new TimeAlignedDataServiceRequest
{
TimeSeriesUniqueIds = timeSeriesId,
QueryFrom = fromDate,
QueryTo = toDate
};
TimeAlignedDataServiceResponse response = await client.Publish.GetAsync(request);
return response;
}
-----------------------------------------------------------
然后,我根据单元测试文档(https://github.com/AquaticInformatics/aquarius-sdk-net/wiki/Unit-testing-your-integration)编写了一个方法的单元测试:
public class AquariusServiceTests
{
private IAquariusClient _mockClient;
private IServiceClient _mockPublishClient;
private IServiceClient _mockProvisioningClient;
private IServiceClient _mockAcquisitionClient;
public AquariusServiceTests()
{
SetupMockClient();
}
private void SetupMockClient()
{
_mockClient = Substitute.For<IAquariusClient>();
_mockPublishClient = Substitute.For<IServiceClient>();
_mockProvisioningClient = Substitute.For<IServiceClient>();
_mockAcquisitionClient = Substitute.For<IServiceClient>();
_mockClient.Publish.Returns(_mockPublishClient);
_mockClient.Provisioning.Returns(_mockProvisioningClient);
_mockClient.Acquisition.Returns(_mockAcquisitionClient);
}
[Fact]
public async Task GetTimeSeriesPointsAsync_Should_Return_Response()
{
List<Guid> timeseriesIds = new() { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
List<TimeAlignedPoint> points = new(1);
TimeAlignedDataServiceRequest request = new()
{
TimeSeriesUniqueIds = new List<Guid> { Guid.NewGuid() },
QueryFrom = DateTime.Now,
QueryTo = DateTime.Now.AddHours(1)
};
TimeAlignedDataServiceResponse response = new()
{
NumPoints = 1,
Points = points,
ResponseTime = new DateTimeOffset(),
ResponseVersion = 1,
Summary = "summary",
TimeRange= new TimeRange(),
TimeSeries=new List<TimeAlignedTimeSeriesInfo>()
};
ILogger<AquariusService> _fakeLogger = Substitute.For<ILogger<AquariusService>>();
IAquariusService _sut = new AquariusService(_fakeLogger);
_mockPublishClient.Get(request).Returns(response);
var actual = await _sut.GetTimeSeriesPointsAsync(_mockClient, timeseriesIds, DateTime.Now, DateTime.Now.AddHours(1));
Assert.IsAssignableFrom<TimeAlignedDataServiceResponse>(actual);
//Exception
//_mockPublishClient.GetAsync(request).ThrowsForAnyArgs(new ArgumentNullException());
//var actual = await Record.ExceptionAsync(() => _sut.GetTimeSeriesPointsAsync(_mockClient, timeseriesIds, DateTime.Now, DateTime.Now.AddHours(1)));
//var error = Assert.IsType<ArgumentNullException>(actual);
}
}
请注意,这些代码部分已经翻译成中文。如果您有其他问题或需要进一步帮助,请随时提问。
英文:
I wrote the bellow method on the AquariusService class which is called Aquarius SDK:
public async Task<TimeAlignedDataServiceResponse> GetTimeSeriesPointsAsync(IAquariusClient client,
List<Guid> timeSeriesId,
DateTimeOffset? fromDate,
DateTimeOffset? toDate)
{
var request = new TimeAlignedDataServiceRequest
{
TimeSeriesUniqueIds = timeSeriesId,
QueryFrom = fromDate,
QueryTo = toDate
};
TimeAlignedDataServiceResponse response = await client.Publish.GetAsync(request);
return response;
}
And then wrote a unit test for the method based on the unit test documents on the (https://github.com/AquaticInformatics/aquarius-sdk-net/wiki/Unit-testing-your-integration):
public class AquariusServiceTests
{
private IAquariusClient _mockClient;
private IServiceClient _mockPublishClient;
private IServiceClient _mockProvisioningClient;
private IServiceClient _mockAcquisitionClient;
public AquariusServiceTests()
{
SetupMockClient();
}
private void SetupMockClient()
{
_mockClient = Substitute.For<IAquariusClient>();
_mockPublishClient = Substitute.For<IServiceClient>();
_mockProvisioningClient = Substitute.For<IServiceClient>();
_mockAcquisitionClient = Substitute.For<IServiceClient>();
_mockClient.Publish.Returns(_mockPublishClient);
_mockClient.Provisioning.Returns(_mockProvisioningClient);
_mockClient.Acquisition.Returns(_mockAcquisitionClient);
}
[Fact]
public async Task GetTimeSeriesPointsAsync_Should_Return_Response()
{
List<Guid> timeseriesIds = new() { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
List<TimeAlignedPoint> points = new(1);
TimeAlignedDataServiceRequest request = new()
{
TimeSeriesUniqueIds = new List<Guid> { Guid.NewGuid() },
QueryFrom = DateTime.Now,
QueryTo = DateTime.Now.AddHours(1)
};
TimeAlignedDataServiceResponse response = new()
{
NumPoints = 1,
Points = points,
ResponseTime = new DateTimeOffset(),
ResponseVersion = 1,
Summary = "summary",
TimeRange= new TimeRange(),
TimeSeries=new List<TimeAlignedTimeSeriesInfo>()
};
ILogger<AquariusService> _fakeLogger = Substitute.For<ILogger<AquariusService>>();
IAquariusService _sut = new AquariusService(_fakeLogger);
_mockPublishClient.Get(request).Returns(response);
var actual = await _sut.GetTimeSeriesPointsAsync(_mockClient, timeseriesIds, DateTime.Now, DateTime.Now.AddHours(1));
Assert.IsAssignableFrom<TimeAlignedDataServiceResponse>(actual);
//Exception
//_mockPublishClient.GetAsync(request).ThrowsForAnyArgs(new ArgumentNullException());
//var actual = await Record.ExceptionAsync(() => _sut.GetTimeSeriesPointsAsync(_mockClient, timeseriesIds, DateTime.Now, DateTime.Now.AddHours(1)));
//var error = Assert.IsType<ArgumentNullException>(actual);
}
}
The issue is the response on GetTimeSeriesPointsAsync() will be null instead of the given response. Actually can't mock the client.Publish.GetAsync(request) correctly while the mock of the exception works fine.
How can I mock client.Publish.GetAsync(request) on the GetTimeSeriesPointsAsync method correctly and return a response instead of null on the test result?
答案1
得分: 0
以下是翻译好的部分:
"Great, there are two things here. First of all, you are mocking the Get()
method in your tests whilst you are calling GetAsync()
in your service. The second point here is that your method signature must be identical in mocking and where you call the actual method. You are creating a request object inside your test, but inside your method you are creating another one, they are two different objects in memory, even though they have the same attribute values. So you need to change this line of your test code
_mockPublishClient.Get(request).Returns(response);
to
_mockPublishClient.GetAsync(Arg.Any<TimeAlignedDataServiceRequest>()).Returns(response);
and if you need to also test the object you are passing inside your service, you'll probably need to modify your class to also pass this object as a parameter."
英文:
Great, there are two things here. First of all, you are mocking the Get()
method in your tests whilst you are calling GetAsync()
in your service.
The second point here is that your method signature must be identical in mocking and where you call the actual method. You are creating a request object inside your test, but inside your method you are creating another one, they are two different objects in memory, even though they have the same attribute values.
So you need to change this line of your test code
_mockPublishClient.Get(request).Returns(response);
to
_mockPublishClient.GetAsync(Arg.Any<TimeAlignedDataServiceRequest>()).Returns(response);
and if you need to also test the object you are passing inside your service, you'll probably need to modify your class to also pass this object as a parameter.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论