我使用Moq和Nunit进行单元测试相当新,我遇到了一个方案的问题。我想要的是我的模拟有一个输出参数,我的系统将用它来决定采取什么行动。
我的测试系统是一个MVC API控制器,特别是我试图测试POST方法。我想在验证失败时返回对象的错误消息。
以下是控制器的方法代码:
[Test]
[Category("CandidateManagerController Unit Tests")]
public void Should_Return_Bad_Request_When_Creating_Invalid_Candidate()
{
IEnumerable<string> errors = new List<string>() {"error1", "error2"};
var mockManager = new Mock<ICandidateManager>();
mockManager.Setup(x => x.InsertCandidate(new Candidate(), out errors)).Callback(()=>GetErrors(errors));
var sut = new CandidateManagerController(mockManager.Object);
var actionResult = sut.Post(new Candidate());
Assert.IsInstanceOf<BadRequestResult>(actionResult);
}
这是我的单元测试代码:
{{1}}
我期望在运行_candidateManager.InsertCandidate()时填充errors变量。但是,当您单步执行控制器时,在运行_candidateManager.InsertCandidate()方法后,错误为空。
如果有人有任何想法我做错了或者我想做什么是不可能使用Moq那么请告诉我。
由于
答案 0 :(得分:1)
你想做的事情是可能的。如果您查看https://github.com/Moq/moq4/wiki/Quickstart处的快速入门文档,可以在其中显示如何使用参数设置方法的设置。我对您的代码进行了两次更正,但它确实有效。
您不必使用Callback来设置模拟的CandidateManager返回的错误。 以下是我的更改的测试方法。
[Test]
[Category("CandidateManagerController Unit Tests")]
public void Should_Return_Bad_Request_When_Creating_Invalid_Candidate()
{
IEnumerable<string> errors = new List<string>() {"error1", "error2"};
//instance to be used for both setup and test later
var candidate = new Candidate();
var mockManager = new Mock<ICandidateManager>();
//removed Callback
mockManager.Setup(x => x.InsertCandidate(candidate, out errors));
var sut = new CandidateManagerController(mockManager.Object);
var actionResult = sut.Post(candidate);
Assert.IsInstanceOf<BadRequestResult>(actionResult);
}
答案 1 :(得分:0)
您必须确保在调用SUT时使用传递给out
参数的相同实例,否则调用将失败。
在您的示例中,测试中的方法将null实例传递给模拟方法,从而否定了测试的设置。
但是,如果您无法为out
提供相同的实例,那么看起来您将无法成功通过模拟。看看Quick Start for Moq,了解它的功能。