示例
我有一个存储库类(DAL):
public class MyRepository : IMyRepository
{
public void Delete(int itemId)
{
// creates a concrete EF context class
// deletes the object by calling context.DeleteObject()
}
// other methods
}
我还有一个服务类(BLL):
public class MyService
{
private IMyRepository localRepository;
public MyService(IMyRepository instance)
{
this.localRepository = instance;
}
public void Delete(int itemId)
{
instance.Delete(itemId);
}
// other methods
}
为MyRepository创建单元测试比实现它需要更多的时间,因为我必须模拟实体框架上下文。
但是为MyService创建单元测试似乎是无稽之谈,因为它只调用Repository。我可以检查的是验证它是否确实调用了存储库删除方法。
问题
您如何建议对这些Delete方法进行单元测试。都?一?没有?你会测试什么?
答案 0 :(得分:1)
是的,两者都是。
IMyRepository mock = ...;
// create Delete(int) expectation
MyService service = new MyService(mock);
service.Delete(100);
// Verify expectations
您现在的Delete方法可能只调用存储库中的Delete方法,但这并不意味着它总是会。您希望对此进行单元测试,以部分验证其行为是否正确,部分是为了定义存储库工作方式的规范。
如果存储库为null,您还应该有一个测试来验证构造函数是否会抛出异常。您可能还需要在此方法中执行其他验证,例如非负ID或非零ID。也许这不会发生在这里,通过创建验证预期行为的测试使其成为规范的一部分。
它们似乎微不足道,但我可以保证它有一天会改变,你的期望和规格可能无法验证。
答案 1 :(得分:1)
是的,我肯定会为服务层编写单元测试。这样做的原因是,您不仅要测试您的实现现在是否正常工作,而且您还测试它将来会继续运行。
这是一个需要理解的重要概念。如果有人稍后出现并更改了ServiceLayer,并且没有单元测试,那么如何验证该功能是否继续有效?
我也会为你的DAL编写测试,但我会将它们放在一个名为DataTests的独立程序集中。这里的目的是隔离您对组件的关注。单元测试真的不应该关注你的DAL。
答案 2 :(得分:0)
为服务创建测试。 目前它所做的只是调用Repository Delete方法;但是,你不应该在意这一点。如果以后发生了什么事情并且功能变得复杂得多怎么办?您是否希望拥有可确保功能仍按预期工作的单元测试代码?
如果您通过自己的服务公开了“删除”,那么您希望它会产生效果。编写单元测试来测试该效果。根据您的特定需求,我会说您可能不需要对Repository Delete进行测试,特别是如果该功能是作为Service Delete功能的一部分进行的,但实际上这取决于您的覆盖范围。重新尝试。
答案 3 :(得分:0)
另外,如果您使用TDD创建了此代码,那么您将进行测试。实际上,人们是否可以通过您的服务呼叫删除,因此您实际上必须对其进行测试。
答案 4 :(得分:0)
在我看来,你需要测试两者。也许你可以在一个单独的工厂中创建EF上下文类,可以更容易地测试并模拟MyRepository测试的上下文类。这将更容易,并且使用工厂创建上下文调用对我来说似乎很安静。