Search code examples
c#unit-testing.net-coresdkxunit.net

How to properly mock client.Publish.GetAsync(request) in Aquarius SDK unit test?


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?


Solution

  • 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.