为什么使用Moq的Verify()进行不确定的单元测试?

我们正在使用Moq 4进行单元测试,尤其是控制器单元测试。我们正在使用Moq的Verify()方法来确保记录了错误。问题在于测试可以通过,但随后的下一次运行将失败。


我们正在使用Serilog作为记录器。


动作方法看起来像


public IActionResult Index(){

    try{

         var data = _repository.GetData();

         return View(data);

    }catch(Exception e){

        Log.Error(e.Message);

    }

}

所以单元测试正在使用


_mockLogger.Verify(x=> x.Write(LogEventLevel.Error,It.IsAny<string>()));

mockLogger 是在测试的构造函数中设置的,例如


var _mockLogger = new Mock<Serilog.ILogger>();

Log.Logger = _mockLogger.Object;

//...

并且该存储库被模拟为在调用时引发异常。


失败时,我们会收到错误消息


“ Moq.MoqException预期在Mock上调用至少一次,但从未执行过x=>x.Write(LogEventLevel.Error,It.IsAny<string>())”


有任何想法吗?


函数式编程
浏览 425回答 1
1回答

慕桂英546537

不可能完全从发布的代码中看到问题所在。而且,我感谢为此制作MCVE会有多艰巨。因此,我将进行两个猜测。猜测1:我怀疑是您的问题的起因是static在代码中使用s,特别是与记录器有关。我怀疑正在发生的事情是其他测试(未在帖子中显示)也在修改/定义记录器的行为,并且由于记录器是静态的,因此这些测试相互干扰。尝试重新设计代码,以便使用serilog的ILogger接口将日志记录功能的实例依赖注入到测试中的类中,并将其存储在只读字段中,并在需要记录时使用。猜想2:根据帖子中“在测试的构造函数中设置...”这一部分,您尚未说出(或标记)您正在使用的测试框架。但是我用过的少数工具希望您在属性方法中而不是在测试的构造函数中执行这种操作。例如,NUnit具有OneTimeSetUp(在运行该类中的任何测试之前),SetUp(在运行该类中的每个测试之前),TearDown(在运行该类中的每个测试之后),OneTimeTearDown(在所有测试之后)在该类中运行)。测试的构造函数可能会以您不期望的顺序被调用,并且测试框架不支持该顺序。而属性方法的顺序由框架保证。
打开App,查看更多内容
随时随地看视频慕课网APP