C# 模拟对象无法返回所需的对象
当我遇到这样的问题时,总会有一些明显的事情我忽略了 我有一个控制器,它只根据提供的ID返回一篇新闻文章:C# 模拟对象无法返回所需的对象,c#,asp.net-mvc-3,nunit,moq,ninject-2,C#,Asp.net Mvc 3,Nunit,Moq,Ninject 2,当我遇到这样的问题时,总会有一些明显的事情我忽略了 我有一个控制器,它只根据提供的ID返回一篇新闻文章: [HandleError] public class HomeController : Controller { private readonly IArticleRepository articleRepository; public HomeController(IArticleRepository Repository) { articleRe
[HandleError]
public class HomeController : Controller
{
private readonly IArticleRepository articleRepository;
public HomeController(IArticleRepository Repository)
{
articleRepository = Repository;
}
public ActionResult Index()
{
return View("Index");
}
// Here's the bit we're interested in
public ActionResult Article(int id)
{
var article = articleRepository.GetById(id);
return View("Article", article);
}
}
我用最小起订量来模拟它,就像这样:
[TestFixture]
public class HomeControllerTests
{
HomeController controller;
int articleId;
Article model;
[TestFixtureSetUp]
public void SetupMethods()
{
Mock<IArticleRepository> repositoryMock = new Mock<IArticleRepository>();
repositoryMock.Setup(x => x.GetById(articleId)).Returns(GetSampleArticle());
controller = new HomeController(repositoryMock.Object);
}
[Test]
public void Article_Action_Returns_Requested_Article()
{
// Arrange
model = new Article();
articleId = 1;
// Act
ActionResult result = controller.Article(articleId);
// Assert
var viewResult = ((ViewResult)result);
var returnedModel = viewResult.Model;
Assert.IsInstanceOf<Article>(viewResult.Model);
//Assert.AreEqual(articleId, returnedModel.ID);
}
}
[TestFixture]
公共类家庭控制器测试
{
家庭控制器;
int articleId;
文章模式;
[TestFixtureSetUp]
公共方法()
{
Mock repositoryMock=新建Mock();
Setup(x=>x.GetById(articleId)).Returns(GetSampleArticle());
控制器=新的HomeController(repositoryMock.Object);
}
[测试]
公共无效文章\行动\返回\请求\文章()
{
//安排
模型=新文章();
articleId=1;
//表演
ActionResult=controller.Article(articleId);
//断言
var viewResult=((viewResult)结果);
var returnedModel=viewResult.Model;
Assert.IsInstanceOf(viewResult.Model);
//aresequal(articleId,returnedModel.ID);
}
}
上面提到的“GetSampleArticle”方法如下所示:
private Article GetSampleArticle()
{
Article article = new Article()
{
Archived = false,
Body = "<p>This is a dummy sample article for use in our mocks.</p>",
EndDate = DateTime.Today.AddDays(30),
ID = 1,
Priority = 3,
StartDate = DateTime.Today,
Title = "Sample Article"
};
return article;
}
私有文章GetSampleArticle()
{
第条=新条款()
{
存档=假,
Body=“这是一篇用于模拟的虚拟示例文章。”,
EndDate=DateTime.Today.AddDays(30),
ID=1,
优先级=3,
StartDate=日期时间。今天,
Title=“示例文章”
};
退货物品;
}
但是,我仍然得到模型的null类型。那么我忘记了什么
News.Tests.Controllers.HomeControllerTests.Article_Action_Returns_Requested_Article:
Expected: instance of <News.Data.Article>
But was: null
News.Tests.Controllers.HomeControllerTests.Article\u Action\u返回\u请求的\u文章:
预期:实例
但是是:空
在SetupMethods中,articleId为0
在测试中,您将其设置为1,因此永远不会调用.Setup
。我会将您的设置移动到您的测试中
[Test]
public void Article_Action_Returns_Requested_Article()
{
// Arrange
model = new Article();
articleId = 1;
Mock<IArticleRepository> repositoryMock = new Mock<IArticleRepository>();
repositoryMock.Setup(x => x.GetById(articleId)).Returns(GetSampleArticle());
controller = new HomeController(repositoryMock.Object);
// Act
ActionResult result = controller.Article(articleId);
// Assert
var viewResult = ((ViewResult)result);
var returnedModel = viewResult.Model;
Assert.IsInstanceOf<Article>(viewResult.Model);
//Assert.AreEqual(articleId, returnedModel.ID);
}
[测试]
公共无效文章\行动\返回\请求\文章()
{
//安排
模型=新文章();
articleId=1;
Mock repositoryMock=新建Mock();
Setup(x=>x.GetById(articleId)).Returns(GetSampleArticle());
控制器=新的HomeController(repositoryMock.Object);
//表演
ActionResult=controller.Article(articleId);
//断言
var viewResult=((viewResult)结果);
var returnedModel=viewResult.Model;
Assert.IsInstanceOf(viewResult.Model);
//aresequal(articleId,returnedModel.ID);
}
在SetupMethods中,articleId为0
在测试中,您将其设置为1,因此永远不会调用.Setup
。我会将您的设置移动到您的测试中
[Test]
public void Article_Action_Returns_Requested_Article()
{
// Arrange
model = new Article();
articleId = 1;
Mock<IArticleRepository> repositoryMock = new Mock<IArticleRepository>();
repositoryMock.Setup(x => x.GetById(articleId)).Returns(GetSampleArticle());
controller = new HomeController(repositoryMock.Object);
// Act
ActionResult result = controller.Article(articleId);
// Assert
var viewResult = ((ViewResult)result);
var returnedModel = viewResult.Model;
Assert.IsInstanceOf<Article>(viewResult.Model);
//Assert.AreEqual(articleId, returnedModel.ID);
}
[测试]
公共无效文章\行动\返回\请求\文章()
{
//安排
模型=新文章();
articleId=1;
Mock repositoryMock=新建Mock();
Setup(x=>x.GetById(articleId)).Returns(GetSampleArticle());
控制器=新的HomeController(repositoryMock.Object);
//表演
ActionResult=controller.Article(articleId);
//断言
var viewResult=((viewResult)结果);
var returnedModel=viewResult.Model;
Assert.IsInstanceOf(viewResult.Model);
//aresequal(articleId,returnedModel.ID);
}
另一个想法是使用It.IsAny()方法来避免查找硬编码值:
repositoryMock.Setup(x => x.GetById(It.IsAny<int>())).Returns(GetSampleArticle());
repositoryMock.Setup(x=>x.GetById(It.IsAny()).Returns(GetSampleArticle());
这样做是安全的,因为您不关心articleId的实际值,而是关心它的检索机制。另一个想法是使用It.IsAny()方法来避免查找硬编码值:
repositoryMock.Setup(x => x.GetById(It.IsAny<int>())).Returns(GetSampleArticle());
repositoryMock.Setup(x=>x.GetById(It.IsAny()).Returns(GetSampleArticle());
这样做是安全的,因为你关心的不是articleId的实际值,而是它的检索机制。好极了。非常感谢。实际上,我将它移动到NUnit[SetUp]修饰的方法中,而不是每次测试都声明它。很好,太棒了。非常感谢。实际上,我将它移动到NUnit[SetUp]修饰的方法中,而不是每次测试都声明它。很好,完全同意。您不应该为设置指定值。相反,当您想要验证值本身时,应该使用Expect(),尽管这是我自己不再做的事情,因为快速阅读代码会告诉我a是否正确地分配给B。甚至更好。我一直想学习更多关于如何更好地使用Moq语法的知识,这是一个非常有用的例子。谢谢。我建议不要在单元测试中使用
IsAny
,除非你必须这样做。它使测试变得脆弱,因为您无法确切地确定传入的内容,也无法确定返回的数据是否正确。如果您传递的是articleId
而不是IsAny
,那么您就知道正在使用正确的参数调用GetById
。这只会让测试更可靠,让你更有信心,因为正确的理由它会通过。这是一个很好的建议,我很感激,但在这种情况下,因为我实际上并不特别关心通过的实际值;只需返回一条伪记录,IsAny
方法就应该适合这种情况。完全同意。您不应该为设置指定值。相反,当您想要验证值本身时,应该使用Expect(),尽管这是我自己不再做的事情,因为快速阅读代码会告诉我a是否正确地分配给B。甚至更好。我一直想学习更多关于如何更好地使用Moq语法的知识,这是一个非常有用的例子。谢谢。我建议不要在单元测试中使用IsAny
,除非你必须这样做。它可以进行测试