我应该将这段代码放在 MVC 中的什么位置?
我的代码运行完美,但是。这种情况下的最佳做法是什么?
这是重要的代码。
这是在控制器中。
private IProductRepository repository;
[HttpPost]
public ActionResult Delete(int productId) {
Product prod = repository.Products.FirstOrDefault(p => p.ProductID == productId);
if (prod != null) {
repository.DeleteProduct(prod);
TempData["message"] = string.Format("{0} was deleted", prod.Name);
}
return RedirectToAction("Index");
}
这是存储库(包括接口等)
public interface IProductRepository {
IQueryable<Product> Products { get; }
void SaveProduct(Product product);
void DeleteProduct(Product product);
}
,这里是存储库......(重要的部分)但我想指出......这不是一个假类,这一点非常清楚。测试是在 fakeclass 上完成的。
private EFDbContext context = new EFDbContext();
public IQueryable<Product> Products {
get { return context.Products; }
}
public void DeleteProduct(Product product) {
context.Products.Remove(product);
context.SaveChanges();
}
那么第一个问题: 在对此进行测试时,我将在“ControllerTest”中的控制器上创建两个测试方法。 “Can_delete_valid_product”和“Cannot_delete_invalid_product”。为存储库提供测试类有什么意义吗?就像“RepositoryTest”一样,毕竟控制器测试删除功能是否有效,不需要测试两次,对吗?
第二个问题: 在此,我在尝试删除产品之前在控制器中测试该产品是否存在。如果存在,我会调用存储库中的删除函数。这意味着永远不应该有例外的可能性。但是如果您发送 null,您仍然可以在存储库中创建异常。 (这在这里不会发生,但如果您忘记检查是否为空,您仍然可以这样做)。问题是产品是否存在的测试是否应该在存储库中完成?
My code works perfectly, BUT. Whats the best practice in this case?
Here is the code that is important.
This is in the controller.
private IProductRepository repository;
[HttpPost]
public ActionResult Delete(int productId) {
Product prod = repository.Products.FirstOrDefault(p => p.ProductID == productId);
if (prod != null) {
repository.DeleteProduct(prod);
TempData["message"] = string.Format("{0} was deleted", prod.Name);
}
return RedirectToAction("Index");
}
This is the repository (both Interface etc)
public interface IProductRepository {
IQueryable<Product> Products { get; }
void SaveProduct(Product product);
void DeleteProduct(Product product);
}
And here comes the repository..... (the part that is important) I want to point out though... that this is not a fakeclass as is pretty clear. The testing is done on fakeclasses.
private EFDbContext context = new EFDbContext();
public IQueryable<Product> Products {
get { return context.Products; }
}
public void DeleteProduct(Product product) {
context.Products.Remove(product);
context.SaveChanges();
}
Well first question:
When doing testing on this, I will make a two TestMethods on the Controller in "ControllerTest". "Can_delete_valid_product" and "Cannot_delete_invalid_product". Is there any point in having a testclass for the repository? Like "RepositoryTest", afterall the controller tests if the deletefunction works no need to test it twice right?
Second question:
In this I test in the controller if the product exists, before trying to delete it. If it exists I call the deletefunction in the repository. This means that there should never be the posibility of an exception. BUT you could still create an exception in the repository if you send down null. (which cant happen here but you could still do it if you forget to check if null). Question is if the testing if product exists should be done in the repository instead?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在大多数情况下,我更喜欢将逻辑保留在控制器之外。控制器操作的测试验证存储库是否被调用,但存储库本身在该测试中被模拟。我会让存储库负责处理空检查。
I prefer to keep logic out of the controller for the most part. A test of the controller action verifies if the repository is called, but the repository itself is mocked in that test. I would make the repository responsible for handling null checking.
我个人为我的存储库/数据访问创建单独的测试,以确保其正常工作。控制器本身将使用模拟进行测试。
实际上,完全有可能(只是可能性不大)某人可以在其他人试图删除产品时删除该产品。在这种情况下,您可能不关心/需要知道有人这样做了,所以我可能会在存储库中吞下该异常(尽管我会先记录它)。就空检查/防御性编程而言,这完全是个人选择。有些人将这样的检查留在系统的入口点,而其他人则构建分层防御,在整个代码中进行额外的检查。问题是这些检查可能会变得相当难看,这也是我希望 代码合约的重要原因 会获得更多关注。
Personally I create separate tests for my repositories/data access to ensure that it works properly. The controllers themselves would be tested with mocks.
Actually it's entirely possible (just maybe not that likely) that someone could delete a product just as someone else is trying to delete it. In this case you probably don't care/need to know that someone did though so I would probably just swallow that exception in the repository (though I would log it first). In terms of null checking/defensive programming that's entirely a personal choice. Some people leave checks like that to the entry points of the system where as others will build a layered defense that has additional checks throughout the code. The problem is that these checks can get quite ugly which is a big part of why I wish Code Contracts would gain more traction.
或者,如果它在您检查它存在之后但在删除它之前被删除。或者,如果您失去了与存储库的连接(或者在这种情况下该方法永远不会返回?)。你无法通过这种方式避免异常。
Or if it's deleted after you check it exists but before you delete it. Or if you lose connection to the repository (or will the method never return in this case?). You can't avoid exceptions in this way.