Класс Mock Abstract с использованием Moq

1

У меня есть приведенный ниже абстрактный класс и метод тестирования. Используя "Moq", я получил следующую ошибку:

Класс Abstact:

   public abstract class UserProvider
{ 
    public abstract UserResponseObject CreateUser(UserRequestObject request, string userUrl);

    public abstract bool IsUserExist(UserRequestObject request, string userUrl);
}

Класс испытания:

  [TestMethod()]
    public void CreateUserTest()
    {
        var mockUserProvider = new Mock<UserProvider>(MockBehavior.Loose);

    //GetUserRequestObject is local method to set data

         mockUserProvider.
            Setup(u => u.CreateUser(GetUserRequestObject(), ""))
            .Returns(new UserResponseObject { uid = "123", uri = userUri }).Verifiable();

         var userProvider = mockUserProvider.Object.CreateUser(GetUserRequestObject(), "");

         mockUserProvider.Verify(u => u.CreateUser(GetUserRequestObject(), ""));
    }

Сообщение об ошибке:

Moq.MockException: ожидаемый вызов на макет хотя бы один раз, но никогда не выполнялся: u => u.CreateUser(.GetUserRequestObject(), "")

Кто-нибудь, пожалуйста, объясните, почему я получил это сообщение и как его решить?

Теги:
unit-testing
moq

4 ответа

4

Причина, по которой вы получаете эту ошибку, состоит в том, что вы устанавливаете ожидание в конкретном экземпляре объекта:

mockUserProvider.Verify(u => u.CreateUser(GetUserRequestObject(), ""));

Это будет сильно зависеть от способа реализации метода. например, эта реализация GetUserRequestObject() создаст новый экземпляр для каждого вызова, и проверка будет всегда терпеть неудачу:

  private UserRequestObject GetUserRequestObject()
  {
     return new UserRequestObject();
  }

В то время как возврат одного и того же экземпляра для установки и проверки будет успешным:

  private UserRequestObject u = new UserRequestObject();
  private UserRequestObject GetUserRequestObject()
  {
     return u;
  }

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

mockUserProvider.Verify(u => u.CreateUser(It.IsAny<UserRequestObject>(),
                        It.IsAny<string>()), Times.Once);

Или предпочтительно экземпляр, который удовлетворяет определенному критерию (Предполагая, что GetUserRequestObject() имеет Name свойства, которое установлено в Bob)

mockUserProvider.Verify(u => u.CreateUser(
                        It.Is<UserRequestObject>(x => x.Name == "Bob"),
                        It.Is<string>(s => s == "")));
  • 1
    Это решение также работает, учитывая +1. Спасибо за ваше решение
  • 0
    Я пробовал эту строку, она показывает приведенную ниже ошибку mockUserProvider.Verify (u => It.Is <UserRequestObject> (u => u.uid == "123")); Ошибка 87 Локальная переменная с именем «u» не может быть объявлена в этой области, поскольку она будет давать другое значение для «u», которое уже используется в «родительской или текущей» области для обозначения чего-либо
Показать ещё 4 комментария
1

очень просто - вы все делаете правильно, но ваша проверка неверна.

вы создаете нового пользователя, но не указали, что он будет создан.

вам нужно использовать это, а не пробелы:

mockUserProvider.
    Setup(u => u.CreateUser(new user, ""))
    .Returns(new UserResponseObject { uid = "123", uri = userUri }).Verifiable();

из этого вам нужно исправить ваш оператор проверки, когда вы проверяете, что сделан новый пользователь:

mockUserProvider.Verify(u => u.CreateUser(It.IsAny<User>()));

это означает, что вы фактически проверяете, создается ли пользовательский объект, а перед тем, как вы проверите то, что ожидаете от результата. это похоже на то, чтобы проверить что-то в этом роде - скажем, вы собираетесь создать произведение искусства, которое вы планируете, и настроите все это (ваш макет). но вы еще не знаете, что вы создадите, поэтому в своей проверке вы создаете произведение искусства и должны убедиться, что это какой-то тип искусства, а не только тот метод, который запускается, когда он возвращает то, что вы не проверяли.

1

Ваш GetUserRequestObject() может возвращать 2 разных экземпляра объекта UserRequestObject.

Убедитесь, что один и тот же экземпляр используется для установки ожиданий и проверки его по вызову. (иначе используйте It.IsAny<UserRequestObject> при установке ожиданий.

1

Moq проверяет ссылку на ваш объект. Вы должны проверить и передать ему тот же объект, который вы использовали в методе настройки:

public void CreateUserTest()
{
    var mockUserProvider = new Mock<UserProvider>(MockBehavior.Loose);

//GetUserRequestObject is local method to set data
     var user = GetUserRequestObject();

     mockUserProvider.
        Setup(u => u.CreateUser(user, ""))
        .Returns(new UserResponseObject { uid = "123", uri = userUri }).Verifiable();

     var userProvider = mockUserProvider.Object.CreateUser(user, "");

     mockUserProvider.Verify(u => u.CreateUser(user, ""));
}

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

public void CreateUserTest()
{
    var mockUserProvider = new Mock<UserProvider>(MockBehavior.Loose);

//GetUserRequestObject is local method to set data

     mockUserProvider.
        Setup(u => u.CreateUser(Is.Any<User>(), ""))
        .Returns(new UserResponseObject { uid = "123", uri = userUri }).Verifiable();

     var userProvider = mockUserProvider.Object.CreateUser(Is.Any<User>(), "");

     mockUserProvider.Verify(u => u.CreateUser(Is.Any<User>(), ""));
}
  • 0
    Это работает, как и ожидалось, учитывая +1. Спасибо за ваше решение.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню