如何使模拟第一次抛出异常,第二次返回值

本文关键字:第二次 返回值 抛出异常 第一次 何使 模拟 | 更新日期: 2023-09-27 18:12:30

我使用Moq作为我的mock框架,我需要测试一个类,当一个特定类型的异常运行时,它将继续尝试,直到情况得到解决,一旦发生执行完成。

所以我需要的是类似于 的东西
myMock = Mock<IFoo>();
myMock.Setup(m => m.Excecute()).Throws<SpecificException>();
myMock.Setup(m => m.Execute());
var classUnderTest = MyClass(myMock);
classUnderTest.DoSomething();
Assert.AreEqual(expected, classUnderTest.Result);

谢谢你的帮助。

如何使模拟第一次抛出异常,第二次返回值

这是一种方法,基于Moq快速入门的例子,每次调用返回不同的值。

var mock = new Mock<IFoo>();
var calls = 0;
mock.Setup(foo => foo.GetCountThing())
    .Returns(() => calls)
    .Callback(() =>
     {
        calls++;
        if (calls == 1)
        {
            throw new InvalidOperationException("foo");
        }
     });
try
{
    Console.WriteLine(mock.Object.GetCountThing());
}
catch (InvalidOperationException)
{
    Console.WriteLine("Got exception");
}
Console.WriteLine(mock.Object.GetCountThing());

如果方法返回void,使用:

var myMock = new Mock<IFoo>();
bool firstTimeExecuteCalled = true;
myMock.Setup(m => m.Execute())
      .Callback(() =>
       {
            if (firstTimeExecuteCalled)
            {
                firstTimeExecuteCalled = false;
                throw new SpecificException();
            }
       });
try
{
    myMock.Object.Execute();
}
catch (SpecificException)
{
    // Would really want to call Assert.Throws instead of try..catch.
    Console.WriteLine("Got exception");
}
myMock.Object.Execute();
Console.WriteLine("OK!");

https://github.com/Moq/moq4/wiki/Quickstart#miscellaneous

设置成员返回不同的值/在顺序调用时抛出异常:

var mock = new Mock<IFoo>();
mock.SetupSequence(f => f.GetCount())
    .Returns(3)  // will be returned on 1st invocation
    .Returns(2)  // will be returned on 2nd invocation
    .Returns(1)  // will be returned on 3rd invocation
    .Returns(0)  // will be returned on 4th invocation
    .Throws(new InvalidOperationException());  // will be thrown on 5th invocation

为什么不编写自己的测试对象来做这些呢?如果只是用于测试,比如:

public class Mock : IFoo
{
     private int _calls;
     public Mock()
     {
         _calls = 0;
     }
     public int Execute()
     {
         _calls++;
         if (_calls == 1)
             throw new Exception();
         return value;
     }
}