Search code examples
c#xunit

xUnit testing live Get request


I am getting a failure on the following test:


[Fact]
        public async Task Return_Expected_Result_From_API()
        {
            // Arrange
            var timer = Stopwatch.StartNew();
            var expectedStatusCode = HttpStatusCode.OK;
            var expectedContent = new List<GetLocationDTO>
            {
                 new GetLocationDTO
                 {
                     Id = 1,
                     Name = "England",
                     ShortName = "Eng"
                 },
                new GetCountryDTO
                {
                    Id = 2,
                    Name = "France",
                    ShortName = "Fr"
                },
                new GetCountryDTO
                {
                    Id = 3,
                    Name = "Lithuania",
                    ShortName = "LT"
                }
            };

            // Act
            var response = await _httpClient.GetAsync("/api/Location");

            // Assert
            await Helpers.AssertResponseWithContentAsync(timer, response, expectedStatusCode, expectedContent);
        }

Here's the helper class for the assertions:

 public static class Helpers
    {
        private const string _jsonMediaType = "application/json";
        private const int _expectedMaxElapsedMilliseconds = 1000;
        private static readonly JsonSerializerOptions _jsonSerializerOptions = new() { PropertyNameCaseInsensitive = true };

        public static async Task AssertResponseWithContentAsync<T>(Stopwatch stopwatch,
            HttpResponseMessage response, HttpStatusCode expectedStatusCode,
            T expectedContent)
        {
            AssertCommonResponseParts(stopwatch, response, expectedStatusCode);
            Assert.Equal(_jsonMediaType, response.Content.Headers.ContentType?.MediaType);
            Assert.Equal(expectedContent, await JsonSerializer.DeserializeAsync<T?>(  // << -- Issue is here 
                await response.Content.ReadAsStreamAsync(), _jsonSerializerOptions));
        }

        private static void AssertCommonResponseParts(Stopwatch stopwatch,
            HttpResponseMessage response, HttpStatusCode expectedStatusCode)
        {
            Assert.Equal(expectedStatusCode, response.StatusCode);
            Assert.True(stopwatch.ElapsedMilliseconds < _expectedMaxElapsedMilliseconds);
        }

        public static StringContent GetJsonStringContent<T>(T model)
        {
            return new(JsonSerializer.Serialize(model), Encoding.UTF8, _jsonMediaType);
        }
    }

The Get endpoint

 [HttpGet]

        public async Task<ActionResult<List<GetLocationDTO>>> GetCountries()
        {
            
            var countries = await _countriesRepository.GetAllAsync<GetLocationDTO>();

            return Ok(countries);
        }

The error I am getting is:

  Duration: 330 ms

  Message: 
Assert.Equal() Failure
           ↓ (pos 0)
Expected: [GetLocationDTO{ Id = 1, Name = "England",···
Actual:   [GetLocationDTO { Id = 1, Name = "England",···
           ↑ (pos 0)

  Stack Trace: 
Helpers.AssertResponseWithContentAsync[T](Stopwatch stopwatch, HttpResponseMessage response, HttpStatusCode expectedStatusCode, T expectedContent) line 0
UnitTestCountriesControllerAndRepository.Return_Expected_Result_From_API() line 91
--- End of stack trace from previous location ---

I have tried calling the actual controller method directly for the expected result:

           var controller = new CountriesController(_mapper, countriesService);
           var expectedContent = await controller.GetCountries().Result;

The expectedStatus and timer are both ok.

I am not sure what the error means, I have tried looking it up but haven't found anything that helps.


Solution

  • As @possum pointed out, the assertion fails because the objects are compared by reference.

    In order to compare by value you need GetLocationDTO to implement IEquatable or use FluentAssertions Should().BeEquivalentTo()