我正试图找出打破单位测试的正确方法。
鉴于以下两个类,一个是CategoryService
,另一个是使用CategoryValidator
的{{1}},您将如何编写这些测试?
我尝试过编写服务测试和验证器测试,但是如何测试验证在服务中是否有效?或者这是否超出了服务测试的范围,应该在验证器测试中涵盖?
在FluentValidation
方法中,我正在测试验证程序中是否已存在类别名称。如何在单元测试中测试?或者那是集成测试吗?
类别服务
AddCategory
类别验证器
public class CategoryService : ValidatingServiceBase, ICategoryService
{
private readonly IUnitOfWork unitOfWork;
private readonly IRepository<Category> categoryRepository;
private readonly IRepository<SubCategory> subCategoryRepository;
private readonly IValidationService validationService;
public CategoryService(
IUnitOfWork unitOfWork,
IRepository<Category> categoryRepository,
IRepository<SubCategory> subCategoryRepository,
IValidationService validationService)
: base(validationService)
{
this.unitOfWork = unitOfWork;
this.categoryRepository = categoryRepository;
this.subCategoryRepository = subCategoryRepository;
this.validationService = validationService;
}
public bool AddCategory(Category category)
{
var validationResult = validationService.Validate(category);
if (!validationResult.IsValid)
return false;
categoryRepository.Add(category);
return true;
}
}
答案 0 :(得分:3)
有些人可能会发现这种异端,但即使测试接近整合而非单元,我也更愿意接受测试。您只需要确保您的检查是全面的。
不要担心测试如何在类之间进行交互,如果你开始进行单元测试(因为我怀疑你是),那么最好编写测试并且TDD的最终D将自然而然地出现。
答案 1 :(得分:1)
我认为您应该单独测试验证器和服务。比如服务测试你可以模拟验证器来返回特定的结果而不会用太多细节污染你的测试逻辑(伪代码)
test Should_Add_Category_Only_If_It_Is_Valid() {
//given
Category category = GivenACategory();
GivenValidatorAcceptsCategory(category);
//when
Bool result = service.AddCategory(category);
//then
AssertTrue(result);
VerifyServiceHasCategory(category);
}
test Should_Reject_Invalid_Category() {
//given
Category category = GivenACategory();
GivenValidatorRejectsCategory(category);
//when
Bool result = service.AddCategory(category);
//then
AssertFalse(result);
VerifyServiceDoesNotHaveCategory(category);
}
答案 2 :(得分:1)
您要解决的问题超出了单元测试的定义。 Unit tests测试单元;)因此,使用存根验证器为服务编写单元测试,并为具有存根服务的验证器编写单元测试。然后编写一些integration tests,这些将验证您的组件是否正确交互。
但是,始终要考虑如何在系统中定义component
(a unit
)。如果您将服务和验证器的功能作为一个包一起公开,那么将它们一起编写单元测试,将它们视为一个单元,并且不要考虑它们如何在内部工作 - 期望只有特定“API”的正确结果(在意义上 - 暴露的界面)调用。
您可以将这两种方法结合起来,并将服务和验证器作为一个单元进行测试,但要使用White-box testing方法了解它的内部结构。但是,对于大型组件而言,这是不受欢迎的,我认为这显然是原因。
最后 - 所有这些名字都很重要吗?它们只是名字,我不能只是测试吗?恕我直言,重要的是要表示单元测试之间的界限 - 它应该测试绝对的一切(意思是“每个单元” - 见上文)。这使您可以随时灵活地重构和重构代码,而不会有更改单元外部行为的风险。第二组是附加测试(如集成,烟雾,白盒,回归测试等) - 因为它们测试系统的较大部分,它们的数量要少得多。它们很重要,因为单元测试不能验证组件之间的所有交互,但它们只测试一些可能的场景。