Как работать с `out` параметрами методов при `Setup`/`Verify` этих методов в мок-классе?

183
14 ноября 2018, 23:30
public class MyClass
{
   public virtual void Method1(string par1, int par2)
   {
      // ...
      var result = new Dictionary<byte, string>();
      for(var i = 0; i < 100; i++)
      {
         if(someCondition) break;
         Method2(par1, out byte res1, out string res2);
         result[res1] = res2;
      }
      // ...
   }
   public virtual void Method2(string par1, out byte res1, out string res2)
   {
      // ...
      res1 = 1;
      res2 = "res2";
      // ...
   }
}
    // test class
public class MyClassTests
{
   [Fact]
   public void TestMethod()
   {
      string par1 = "value";
      int par2 = 2;
      var myClassMock = new Mock<MyClass>() { CallBase = true };
      myClassMock.Verify(v => v.Method1(par1, par2), Times.Once);
      myClassMock.Verify(v => v.Method2(It.IsAny<string>(), out ?, out ?), Times.AtMost(3));
   }
}

В зависимости от некоторого условия, количество вызовов Method2 не должно превышать 3. Тест проверяет, срабатывает ли эта логика для конкретного запроса или нет.

Проблема в том, что невозможно установить все возможные варианты для выходных параметров и тут мне бы подошла конструкция с It.IsAny<>(), однако для out параметров это не работает.

Есть ли какие-то варианты для подобных кейсов?

Answer 1

Есть два варианта:

  1. Простой — передать неиспользуемую переменную (дискарды — _, к сожалению, не поддерживаются в выражениях).

    byte b;
    string s;
    myClassMock.Verify(
        v => v.Method2(It.IsAny<string>(), out b, out s),
        Times.AtMost(3));
    
  2. Непростой (для версий Moq 4.8+) — ввод ref-матчей, как выяснилось — для out параметров они тоже подходят.

    myClassMock.Verify(
        v => v.Method2(It.IsAny<string>(),
                       out It.Ref<byte>.IsAny,
                       out It.Ref<string>.IsAny),
        Times.AtMost(3));
    

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

READ ALSO
C# DefaultView - добавить значение

C# DefaultView - добавить значение

Прошу помогите мне разобраться:

150
Как получить доступ ко всем свойствам объекта, не используя &#171;отражение&#187; c#

Как получить доступ ко всем свойствам объекта, не используя «отражение» c#

делаю маппер из одного класса в другой, как я могу получить все свойства объекта не прибегая к отражению, для того чтобы их обработать и преобразовать...

164
Как правильно использовать get и set в C# [дубликат]

Как правильно использовать get и set в C# [дубликат]

На данный вопрос уже ответили:

236
Авторизация клиента на сервере

Авторизация клиента на сервере

Задача такая: пользователь Иванов на своем доменном компьютере заходит на клиент который подключается к серверуЗадача сервера понять что...

172