Использование xUnit inlineData, когда параметр является длинной строкой - PullRequest
0 голосов
/ 07 февраля 2020

Я пытаюсь преобразовать 4 почти идентичных тестовых случая в один, где вместо этого используется xUnits InlineData.

Дело в том, что параметр, который я хочу отличать, - это длинная строка - на самом деле JSON - «строка» с небольшими изменениями. Это выглядит так (я только взял соответствующий):

....
....
        var mockHttp = new Mock<HttpMessageHandler>(MockBehavior.Strict);

        mockHttp
            .Protected()
            .Setup<Task<HttpResponseMessage>>(
                "SendAsync",
                ItExpr.IsAny<HttpRequestMessage>(),
                ItExpr.IsAny<CancellationToken>())
            .ReturnsAsync(new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK,
                Content = new StringContent( // the below part is the only thing that differs
                    "{'content':[" +
                        "{'Id':'00001', 'eNumber':'001', 'isOwner': true, 'isAlone':false}," +
                        "{'Id':'00001', 'eNumber':'no', 'isOwner': false, 'isAlone':false}," +
                        "{'Id':'00001', 'eNumber':'no', 'isOwner': false, 'isAlone':false}," +
                        "{'Id':'00001', 'eNumber':'no', 'isOwner': false, 'isAlone':false}," +
                        "]}"
                    )
            })
            .Verifiable();

        var httpClient = new HttpClient(mockHttp.Object)
        {
            BaseAddress = new Uri("http://something.com/")
        };

Следующий тест содержит то же самое, но с другим «контентом», который выглядит так:

....
....
                   "{'content':[" +
                    "{'Id':'00001', 'eNumber':'no', 'isOwner': false, 'isAlone':false}," +
                    "{'Id':'00001', 'eNumber':'002', 'isOwner': false, 'isAlone':true}," +
                    "{'Id':'00001', 'eNumber':'no', 'isOwner': false, 'isAlone':false}," +
                    "{'Id':'00001', 'eNumber':'no', 'isOwner': false, 'isAlone':false}," +
                    "]}"
....
....

и третий выглядит так:

....
....
                   "{'content':[" +
                    "{'Id':'00001', 'eNumber':'no', 'isOwner': false, 'isAlone':false}," +
                    "{'Id':'00001', 'eNumber':'no', 'isOwner': false, 'isAlone':true}," +
                    "{'Id':'00001', 'eNumber':'007', 'isOwner': true, 'isAlone':true}," +
                    "{'Id':'00001', 'eNumber':'003', 'isOwner': false, 'isAlone':false}," +
                    "]}"
....
....

и так далее, с двумя следующими. Поэтому мне интересно, есть ли разумный способ поместить 5 типов содержимого в InlineData в качестве параметра - и тем самым каким-то образом сохранить много скопированного кода? Наверное, есть, но я все еще не понял, как, вообще-то, не написав много кода.

Запись тестов в виде 5 отдельных тестов - все это становится зеленым, поэтому единственное, что я ищу, - это более разумный способ. писать код, делая его чище и проще для чтения, изменяя только параметр / строку внутри StringContent.

Обновление в соответствии с вопросом в комментариях:

Класс Я тестирую что-то вроде этого:

....
....

        var httpResponseMessage = await User(// something);


        if (!httpResponseMessage .IsSuccessStatusCode) return;

        var content = await httpResponseMessage.Content.ReadAsStringAsync();
        var deserializedContent = JsonConvert.DeserializeObject<UserModel>(content); // it fails here...

....
....

мой класс UserModel выглядит так:

public class UserModel
{
    public UserModelDto[] {get; set;}
}

и мой класс UserModelDto выглядит так:

    public class UserModelDto
{
    public string Id{ get; set; }
    public string ENumber { get; set; }
    public bool IsOwner { get; set; }
    public bool IsAlone { get; set; }
}

1 Ответ

1 голос
/ 07 февраля 2020

Расширяя мой комментарий и предоставляя ответ, вы можете использовать MemberDataAttribute или ClassDataAttribute для достижения этой цели. В этом примере используется MemberDataAttribute.

Сначала создайте класс для представления вашей модели.

public class UserModel
{
    [JsonProperty("content")]
    public UserModelDto[] {get; set;}
}

public class UserModelDto
{
    [JsonProperty("id")]
    public string Id{ get; set; }
    [JsonProperty("eNumber")]
    public string ENumber { get; set; }
    [JsonProperty("isOwner")]
    public bool IsOwner { get; set; }
    [JsonProperty("isAlone")]
    public bool IsAlone { get; set; }
}

Добавьте свойство или метод public static IEnumerable<object[]> в ваш тестовый класс, который также содержит ваш тестовый сценарий ios.

public static IEnumerable<object[]> TestCaseScenarios
    => new object[][]
       {
           new object[]
           {
               new UserModel
               {
                   Contents = new[]
                   {
                       new UserModelDto
                       {
                           Id = "00001",
                           ENumber = "no",
                           IsOwner = false,
                           IsAlone = false
                       },
                       new UserModelDto
                       {
                           Id = "00001",
                           ENumber = "007",
                           IsOwner = true,
                           IsAlone = true
                       },
                   }
               }
           },
           new object[] { } //etc
       }

Примените MemberDataAttribute к вашему тесту

[Theory] // Tests which accept parameters require the TheoryAttribute, instead of FactAttribute
[MemberData(nameof(TestCaseScenarios))]
public async Task PerformingAction_WithCriteria_ReturnsExpectedThing(UserModel userModel)
{
    // Serialize userModelto create a string
    var userModelAsString = JsonConvert.SerializeObject(userModel);
    // Create the StringContent object
    var stringContent = new StringContent(userModelAsString);
    // Create a HttpClient whose BaseAddress is the host address

    var mockHttp = new Mock<HttpMessageHandler>(MockBehavior.Strict);

    mockHttp
        .Protected()
        .Setup<Task<HttpResponseMessage>>(
            "SendAsync",
            ItExpr.IsAny<HttpRequestMessage>(),
            ItExpr.IsAny<CancellationToken>())
        .ReturnsAsync(new HttpResponseMessage()
        {
            StatusCode = HttpStatusCode.OK,
            Content = new StringContent(stringContent)
        })
        .Verifiable();

    var httpClient = new HttpClient(mockHttp.Object) { BaseAddress = new Uri("http://something.com") };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...