Gre*_*egS 35 testing installation moq mocking verify
如果需要设置返回值,以及验证调用表达式的次数,可以在一个语句中执行此操作吗?
从我可以收集到的,Moq的Setup(SomeExpression).Verifiable()调用Verify(),基本上是一个Verify(SomeExpression, Times.AtLeastOnce)?即它验证表达式只被调用.
这是一个更好地解释问题的例子.对于接口:
interface IFoo
{
int ReturnSomething();
}
Run Code Online (Sandbox Code Playgroud)
以下两个块是否等效(除了第一个将验证标记为可验证的所有设置)?
void Test()
{
var mock = new Mock<IFoo>();
mock.Setup((m) => m.ReturnSomething()).Returns(1).Verifiable();
mock.Verify();
}
Run Code Online (Sandbox Code Playgroud)
和
void Test()
{
var mock = new Mock<IFoo>();
mock.Setup((m) => m.ReturnSomething()).Returns(1);
mock.Verify((m) => m.ReturnSomething(), Times.AtLeastOnce());
}
Run Code Online (Sandbox Code Playgroud)
如果我想验证调用次数(比如两次),这是唯一的方法,其中表达式重复进行安装和验证吗?
void Test()
{
var mock = new Mock<IFoo>();
mock.Setup((m) => m.ReturnSomething()).Returns(1);
mock.Verify((m) => m.ReturnSomething(), Times.Exactly(2));
}
Run Code Online (Sandbox Code Playgroud)
我只是不喜欢打电话给安装和验证.好吧,因为这对AAA来说是一个好主意,换句话说,我不喜欢重复设置和验证的表达式.目前我将表达式存储在变量中并将其传递给每个方法,但感觉不是那么干净.
PS - 上下文用于检查何时更新缓存(explirations等)的测试
Tre*_*ley 16
要回答第一个问题,是的,这两个块是等价的..Verify如果未调用mock上的方法,则两者都将失败.
据我所知,您无法预先指定验证,如果您考虑它,它是有道理的.
这是指定模拟的行为:
mock.Setup(m => m.ReturnSomething()).Returns(1);
Run Code Online (Sandbox Code Playgroud)
这是验证调用者的行为:
mock.Verify(m => m.ReturnSomething(), Times.AtLeastOnce());
Run Code Online (Sandbox Code Playgroud)
我个人更喜欢单独调用验证以确认调用者所需的行为,.Verifiable()并且.Verify()是不太严格的快捷方式(他们只是检查方法被调用了一次或多次)但是如果你知道你的代码应该只调用一次方法,那么最后验证确认.
我开始这样做之后,代码合并导致一个方法被调用两次,测试仍然通过,因为它被调用至少一次,但它也意味着其他事情多次发生,不应该有!
Evr*_*glu 15
我一直都有这个问题.我使用严格的模拟,我想严格指定(即我使用It.Is<>()而不是It.IsAny())以及严格验证(即指定时间).你不能遗憾地使用可验证的,因为Moq缺少Verifiable(Times)过载.
电话的完整表达,包括It.Is<>()一般都很大.因此,为了避免重复,我通常采用以下方法:
Expression<Action<MockedType>> expression = mockedTypeInstance => mockedTypeInstance.MockedMethod(It.Is<TFirstArgument>(firstArgument => <some complex statement>)/*, ...*/);
_mock.Setup(expression);
/* run the test*/
_mock.Verify(expression, Times.Once);
Run Code Online (Sandbox Code Playgroud)
不是非常易读,但我认为还没有其他方法可以使用严格的设置和严格的验证.
在解释Evren Kuzucuoglu的答案时,我创建了以下扩展方法以使表达式的创建更加简单:
/// <summary>
/// Creates a method call expression that can be passed to both <see cref="Setup"/> and <see cref="Verify"/>.
/// </summary>
/// <typeparam name="T">Mocked object type.</typeparam>
/// <param name="mock">Mock of <see cref="T"/>.</param>
/// <param name="expression">Method call expression to record.</param>
/// <returns>Method call expression.</returns>
public static Expression<Action<T>> CallTo<T>(this Mock<T> mock, Expression<Action<T>> expression) where T : class
{
return expression;
}
/// <summary>
/// Creates a method call expression that can be passed to both <see cref="Setup"/> and <see cref="Verify"/>.
/// </summary>
/// <typeparam name="T">Mocked object type.</typeparam>
/// <typeparam name="TResult">Method call return type.</typeparam>
/// <param name="mock">Mock of <see cref="T"/>.</param>
/// <param name="expression">Method call expression to record.</param>
/// <returns>Method call expression.</returns>
public static Expression<Func<T, TResult>> CallTo<T, TResult>(this Mock<T> mock, Expression<Func<T, TResult>> expression) where T : class
{
return expression;
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
var createMapperCall = mockMappingFactory.CallTo(x => x.CreateMapper());
mockMappingFactory.Setup(createMapperCall).Returns(mockMapper.Object);
mockMappingFactory.Verify(createMapperCall, Times.Once());
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14789 次 |
| 最近记录: |