У меня есть приведенный ниже абстрактный класс и метод тестирования. Используя "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(), "")
Кто-нибудь, пожалуйста, объясните, почему я получил это сообщение и как его решить?
Причина, по которой вы получаете эту ошибку, состоит в том, что вы устанавливаете ожидание в конкретном экземпляре объекта:
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 == "")));
очень просто - вы все делаете правильно, но ваша проверка неверна.
вы создаете нового пользователя, но не указали, что он будет создан.
вам нужно использовать это, а не пробелы:
mockUserProvider.
Setup(u => u.CreateUser(new user, ""))
.Returns(new UserResponseObject { uid = "123", uri = userUri }).Verifiable();
из этого вам нужно исправить ваш оператор проверки, когда вы проверяете, что сделан новый пользователь:
mockUserProvider.Verify(u => u.CreateUser(It.IsAny<User>()));
это означает, что вы фактически проверяете, создается ли пользовательский объект, а перед тем, как вы проверите то, что ожидаете от результата. это похоже на то, чтобы проверить что-то в этом роде - скажем, вы собираетесь создать произведение искусства, которое вы планируете, и настроите все это (ваш макет). но вы еще не знаете, что вы создадите, поэтому в своей проверке вы создаете произведение искусства и должны убедиться, что это какой-то тип искусства, а не только тот метод, который запускается, когда он возвращает то, что вы не проверяли.
Ваш GetUserRequestObject()
может возвращать 2 разных экземпляра объекта UserRequestObject
.
Убедитесь, что один и тот же экземпляр используется для установки ожиданий и проверки его по вызову. (иначе используйте It.IsAny<UserRequestObject>
при установке ожиданий.
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>(), ""));
}