我是ASP.NET MVC和单元测试的新手,我不知道如何为这些方法编写测试方法:
configure(feathers.socketio(socket))
我已经编写了这段代码用于测试,但这还不够。
// GET: Worts/Details
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var wort = (from s in db.Worts
where s.ID == id
select s).FirstOrDefault();
if (wort == null)
{
return HttpNotFound();
}
return View(wort);
}
// GET: Worts/Create
public ActionResult Create()
{
return View();
}
// POST: Worts/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Title,CreateDate,ClickCount,DislikeCount,LikeCount, Creator_ID")] Wort wort)
{
if (ModelState.IsValid)
{
wort.CreateDate = DateTime.Now;
wort.ClickCount = 0;
wort.DislikeCount = 0;
wort.LikeCount = 0;
var userId = User.Identity.GetUserId();
wort.Creator = db.Users.Where(x => x.ID == userId).FirstOrDefault();
db.Worts.Add(wort);
db.SaveChanges();
try
{
this.mailSender.SendEmail(wort);
return RedirectToAction("Index");
}
catch (Exception)
{
throw;
}
}
return View(wort);
}
// GET: Worts/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Wort wort = db.Worts.Find(id);
if (wort == null)
{
return HttpNotFound();
}
return View(wort);
}
// POST: Worts/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "ID,Title,CreateDate")] Wort wort)
{
if (ModelState.IsValid)
{
db.Entry(wort).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(wort);
}
// GET: Worts/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Wort wort = db.Worts.Find(id);
if (wort == null)
{
return HttpNotFound();
}
return View(wort);
}
// POST: Worts/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Wort wort = db.Worts.Find(id);
db.Worts.Remove(wort);
db.SaveChanges();
return RedirectToAction("Index");
}
有人可以帮我为这些方法编写正确完整的测试单元吗?
答案 0 :(得分:1)
我的第一个建议是将您的业务逻辑与您的管道分开。
考虑以下代码:
// GET: Worts/Details
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var wort = (from s in db.Worts
where s.ID == id
select s).FirstOrDefault();
if (wort == null)
{
return HttpNotFound();
}
return View(wort);
}
首先,让我们将数据库调用移动到自己的库中。
// GET: Worts/Details
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var wort = WortService.GetWort(id);
if (wort == null)
{
return HttpNotFound();
}
return View(wort);
}
由于WortService没有任何ASP.NET MVC内容,因此测试起来会容易得多。
现在让我们看一下样板文件。 ASP.NET MVC的一个有趣的事情是你可以使用"异常过滤器"。你需要两个。
您的服务层将根据需要抛出这两个例外。
现在你的MVC层就是:
// GET: Worts/Details
public ActionResult Details(int? id)
{
var wort = WortService.GetWort(id);
return View(wort);
}
这很简单,它不需要自己的测试。您的大部分测试都是针对WortService的,其余的测试都包含在您执行的任何UI测试中。
public class WortService {
public LWContext dbLW = new LWContext();
public Wort GetWort(int? id)
{
if (id == null)
throw new ArgumentNullException("id");
var wort = (from s in dbLW.Worts where s.ID == id select s).FirstOrDefault();
return wort;
}
}
public class ArgumentExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is ArgumentException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.BadRequest);
}
}
}
答案 1 :(得分:0)
这是Microsoft的直接方法
它与WebApi有关,对MVC的工作方式是否相同。我还使用了像Moq或FakeItEasy这样的模拟框架,而不是创建一个TestStoreAppContext类。
答案 2 :(得分:0)
您需要先分离本地版本,然后再执行更新过程
var localEntity = dbContext.Set<theModel>()
.Local
.FirstOrDefault(f => f.Id == theModel.Id);
if (localEntity != null)
{
dbContext.Entry(localEntity).State = EntityState.Detached;
}
dbContext.Entry(appModel).State = EntityState.Modified;