【发布时间】:2013-11-08 00:08:11
【问题描述】:
我正在尝试为一个简单的 mvc 控制器编写一个单元测试,该控制器对数据库进行复杂的 LINQ 查询:
public class HomeController
{
private readonly DamagesDbContext db;
public HomeController(DamagesDbContext db)
{
this.db = db;
}
// GET: /Home/
[Authorize]
public ActionResult Index()
{
var dashData = (from inc_c in db.incident_content
join inc in db.incidents
on inc_c.incidentid equals inc.incidentid
where inc.currentrevisionnumber == inc_c.revisionnumber
group inc_c by 1 into g
select new{
total = g.Count(),
open = g.Count(q => q.incidentstatus == "OPEN"),
closed = g.Count(q => q.incidentstatus == "CLOSED")
}).SingleOrDefault();
ViewBag.total = dashData.total;
ViewBag.open = dashData.open;
ViewBag.closed = dashData.closed;
return View();
}
}
然后在我的测试中,我有:
var mockDb = new Mock<DamagesDbContext>();
mockDb.Setup(/* What goes here? */);
var homeController = new HomeController(mockDb.Object);
var result = homeController.Index();
// Various asserts go here...
但是我在 Setup() 中应该做些什么来替换那个复杂的 LINQ 查询呢?
我如何知道调用了哪些实际方法?或者他们的论点是什么?
==== 已编辑 ====
我认为我的部分问题是 LINQ 表达式虽然有点简洁,但并没有明确说明在哪些对象上调用了哪些方法。
我第一次使用 Resharper,我只是注意到它有一个“将 LINQ 转换为方法链”选项。完成后,上面的 LINQ 表达式变为:
var dashData = (this.db.incident_content.Join(this.db.incidents, inc_c => inc_c.incidentid,
inc => inc.incidentid, (inc_c, inc) => new {inc_c, inc})
.Where(@t => @t.inc.currentrevisionnumber == @t.inc_c.revisionnumber)
.GroupBy(@t => 1, @t => @t.inc_c)
.Select(g => new
{
total = g.Count(),
open = g.Count(q => q.incidentstatus == "OPEN"),
closed = g.Count(q => q.incidentstatus == "CLOSED")
})).SingleOrDefault();
这可能会更清楚地说明需要模拟哪些对象和方法。
【问题讨论】:
-
附带说明:不要使用
ViewBag。请改用模型。 -
这不是生产代码,它只是一个尚未确定的功能的占位符。届时,我们将定义一个模型并将 DB 功能移动到业务层类中。但是当我们这样做时,我们仍然不知道如何模拟数据库查询。
标签: c# linq entity-framework unit-testing moq