Кілька Moq It. Це <string> () Відповідні аргументи


77

З Moq, чи дійсно мати більше одного аргументу, що відповідає?

It.Is<string>() 

У цьому прикладі я хочу, щоб mockMembershipService повернув інший ProviderUserKey залежно від наданого Користувача.

mockMembershipService.Setup(
    x => x.GetUser(
      It.Is<string>(
        s => s.Contains("Joe")))
   .ProviderUserKey)
.Returns("1234abcd");


mockMembershipService.Setup(
  x => x.GetUser(
    It.Is<string>(
      s => s.Contains("Tracy")))
  .ProviderUserKey)
.Returns("5678efgh");

SetUp за замовчуванням має друге твердження, а не оцінює кожен по суті.

Відповіді:


54

Хіба це не бентежить? Ви намагаєтеся знущатись із методу GetUser, але ви встановлюєте Повернення для властивості функції, що повертає значення. Ви також хочете вказати властивість типу return, засновану на висміюваному методі.

Ось спосіб більш чіткого способу:

mockMembershipService.Setup(x => x.GetUser(It.IsAny<string>())
                     .Returns<string>(GetMembershipUser);

Ось метод створення макету членства:

private MembershipUser GetMembershipUser(string s)
{
    Mock<MembershipUser> user =new Mock<MembershipUser>();
    user.Setup(item => item.ProviderUserKey).Returns(GetProperty(s));
    return user.Object;
}

Потім ви пишете метод для встановлення цієї властивості:

private string GetProperty(string s)
{
    if(s.Contains("Joe"))
        return "1234abcd";
    else if(s.Contains("Tracy"))
        return "5678efgh";
}

1
Спробую це незабаром, дивився це відео thethoughtfulcoder.com/blog/52/…, поки ви додали свою відповідь, яка робить щось подібне
Ніколас Мюррей

у наведеному вище коді не буде компіляції, він скаржиться на Security.MembershipUser не містить посилання на повернення, а також на Користувача, що не містить визначення для ProviderUserKey
Ніколас Мюррей

Ви повинні посилатися на збірку, що стосується Security.MembershipUser, я думаю. Або ви можете внести залежність для створення користувачів для вас у вашій
службі

хммм - він не скаржиться на це, коли я намагаюся прокласти свій шлях - (що не працює, як це звичайно)
Ніколас Мюррей

Я думаю, ви можете написати іншу функцію для створення макету MembershipUser, але це серйозно виходить з-під контролю. Я оновив код.
Ufuk Hacıoğulları

35

Якщо ви хочете обмежити введення лише "Джо" і "Трейсі", ви можете вказати кілька умов у It.Is<T>(). Щось на зразок

mockMembershipService.Setup(x => x.GetUser(It.Is<String>(s => s.Contains("Joe") 
                                                         || s.Contains("Tracy")))
    .Returns<string>(/* Either Bartosz's or Ufuk's answer */);

це не те, що я хочу обмежувати сам по собі, я просто хочу оцінити, який вхід і повернути бажаний результат :-)
Ніколас Мюррей

Незалежно від того, чи це було в потрібному місці, це мені допомогло, дякую @ cadrell0
Jacob McKay

15

Послідовні виклики налаштування зводять нанівець попередні налаштування.

Ви можете використати свій аргумент у зворотному зворотному виклику:

mockMembershipService.Setup(x => x.GetUser(It.IsAny<string>()).ProviderUserKey).Returns<string>(s =>
{
    if(s.Contains("Joe"))
        return "1234abcd";
    else if(s.Contains("Tracy"))
        return "5678efgh";
});

Якщо вам важливо затвердити переданий аргумент, вам також потрібно It.Is<string>(...)замість It.IsAny<string>(...).


Я мав би спробувати це приблизно за 2 години.
Ніколас Мюррей

Ну добре, я думаю, це тому, що ми тут створюємо власність ( ProviderUserKey), тоді як аргумент, на який ми намагаємося діяти, походить GetUser(...). Наразі не вдається перевірити правильне рішення, але якщо ви будете слідувати порадам Ufuk, це має бути нормально ...
Bartosz

Проведу на вихідних - дякую за допомогу! Не так прямо вперед, як я спочатку думав.
Ніколас Мюррей

@mattumotu: Це не те, що я відчуваю, Moq просто має дивну політику виконання. Пізніше додані налаштування викликів оцінюються спочатку (або завжди оцінюються всі і останні перемоги). Це якраз протилежне тому, чого можна було б очікувати: Зазвичай перший матч повертається, а решта ігнорується.
Крістоф,

7

Будь ласка, перевірте Вступ до Moq> Документація щодо відповідності аргументів :

// matching Func<int>, lazy evaluated
mock.Setup(foo => foo.Add(It.Is<int>(i => i % 2 == 0))).Returns(true); 


// matching ranges
mock.Setup(foo => foo.Add(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns(true); 


// matching regex
mock.Setup(x => x.DoSomething(It.IsRegex("[a-d]+", RegexOptions.IgnoreCase))).Returns("foo");

3
Тепер, маючи більше досвіду в модульних тестах, я не рекомендую такий підхід. Нам слід уникати вкладання логіки в модульні тести. Інший варіант - створення відокремлених модульних тестів: один для Джо, а інший для Трейсі
Джайдер,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.