使用moq,通常使用T
为接口类型Mock.Of<T>()
提供模拟。但是,It.IsAny<T>()
或者T
返回一个表达式,它似乎也可以用作对象来代替It.IsAny<T>()
类型的对象。我只看到Setup()
用于定义Mock.Of<T>()
中方法调用的参数。 It.IsAny<T>()
和It.IsAny<T>()
之间有什么区别(除了语法之外)?在任何情况下都应使用Mock.Of<T>()
来模拟new UserService()
吗?
以下是我要问的一个例子,我将以Ufuk的答案为基础。提供给It.IsAny<IUserRepository>()
的模拟可以是Mock.Of<IUserRepository>()
或Assert.IsTrue()
。在这种情况下,我不想对这些模拟设置任何特殊的东西,只是它们存在以满足编译器。出于这些测试的目的,IUserRepository
语句与提供的It.IsAny<IUserRepository>()
无关。问题是:在此实例中,Mock.Of<IUserRepository>()
和[TestFixture]
public class MoqTests
{
[Test]
public void TestInitializationWithItIsAny()
{
var subject = new UserService( It.IsAny<IUserRepository>() ); // It.IsAny<T>
_userService.RegisterUser("abc");
Assert.IsTrue( _userService.IsInitialized() );
}
[Test]
public void TestInitializationWithMockOf()
{
var subject = new UserService( Mock.Of<IUserRepository>() ); // Mock.Of<T>
_userService.RegisterUser("abc");
Assert.IsTrue( _userService.IsInitialized() );
}
}
public class UserService
{
private readonly IUserRepository _userRepository;
private bool _isInitialized = false;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public bool RegisterUser(string userName)
{
_isInitialized = true;
User user = new User { UserName = userName, CreatedOn = DateTime.Now };
return _userRepository.RegisterUser(user);
}
public bool IsInitialized()
{
return _isInitialized;
}
}
public interface IUserRepository
{
bool RegisterUser(User user);
}
public class User
{
public string UserName { get; set; }
public DateTime CreatedOn { get; set; }
}
在功能上是否相同?
{{1}}
答案 0 :(得分:7)
It.IsAny<T>
用于跳过模拟方法参数中的验证。
serviceMock.Setup(mock => mock.GetUser(It.IsAny<int>())).Returns(someResult);
您必须在模拟回调中传递一个整数作为参数才能进行测试编译。您可能不知道将哪些值发送到模拟组件(对于引用类型通常是真的),或者您甚至可能不关心。 It.IsAny<T>()
为您提供编写测试而不会超出规范。
It.IsAny<T>()
会返回T
的实例,而不是Mock<T>
,因此它不是模拟。
看看这些测试用例:
[TestFixture]
public class MoqTests
{
private Mock<IUserRepository> _repository;
private UserService _userService;
[SetUp]
public void Setup()
{
_repository = new Mock<IUserRepository>(MockBehavior.Strict);
_userService = new UserService(_repository.Object);
}
[Test]
public void RegisterUserWithItIsAny()
{
_repository.Setup(item => item.RegisterUser(It.IsAny<User>())).Returns(true);
bool result = _userService.RegisterUser("abc");
Assert.True(result);
}
[Test]
public void RegisterUserWithMockOf()
{
_repository.Setup(item => item.RegisterUser(Mock.Of<User>())).Returns(true);
bool result = _userService.RegisterUser("abc");
Assert.True(result);
}
[TearDown]
public void TearDown()
{
_repository.VerifyAll();
}
}
public class UserService
{
private readonly IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public bool RegisterUser(string userName)
{
User user = new User { UserName = userName, CreatedOn = DateTime.Now };
return _userRepository.RegisterUser(user);
}
}
public interface IUserRepository
{
bool RegisterUser(User user);
}
public class User
{
public string UserName { get; set; }
public DateTime CreatedOn { get; set; }
}
第二次测试失败,因为Moq无法将模拟实例识别为参数值。当您想要使用谓词参数中包含的单个设置快速创建模拟时,Mock.Of<T>()
似乎很有用。
<强>更新强>
我在你的例子中改写了测试。
[SetUp]
public void Setup()
{
_userService = new UserService(It.IsAny<IUserRepository>());
}
[Test]
public void RegisterUserWithItIsAny()
{
bool result = _userService.RegisterUser("abc");
Assert.True(result);
}
[Test]
public void RegisterUserWithMockOf()
{
bool result = _userService.RegisterUser("abc");
Assert.True(result);
}
两个测试都失败,因为It.IsAny<T>()
返回null。如果您使用过Mock.Of<T>()
,则会创建一个具有默认行为的模拟。这意味着在这种情况下它们在功能上也不相同。