不仅仅是一个实际案例,这是我在尝试获得单元测试和集成测试之间的详细差异时遇到的问题。
假设我有类Sum,它增加了两个整数:
class Sum{
int x;
int y;
public int add(){
return x + y;
}
...getters and setters...
}
我还有另一个负责验证结果的课程,以确认这些数据是预期的。仅举例来说,让我们说我们只想添加正数:
class ValidateSum{
Sum sum;
public boolean validate(){
if(sum.getX()>=0 and sum.getY()>=0){
return true;
}
else{
return false;
}
}
... getters and setters...
}
使用ValidateSum可能没有多大意义,但我们只是为了举例而假设它。
现在我想为ValidateSum编写测试。如果我这样做:
@Test
public void testValidateSum(){
ValidateSum vs = new ValidateSum();
Sum sum = new Sum();
vs.setSum(sum);
boolean result = vs.validate();
assertTrue(result);
}
是单元测试还是集成测试?
我知道单元测试只需验证ValidateSum中的功能,并且在某种程度上测试是这样做的:它只从Sum获取属性,而不是它的任何功能。
但另一方面,你也可以说你正在从Sum访问功能,即使ValidateSum只调用了getter。 Sums吸气剂的任何变化都会影响ValidateSum的测试,打破了单元测试的概念。
但如果是这种情况并且确实是集成测试,那么我如何为ValudateMethod的validate()编写单元测试?
我唯一能想到的就是嘲笑Sum,所以它也会返回相同的值。即使Sum的getter中的逻辑发生变化,ValidateSum的测试仍将保持不变。问题是,模拟getter的响应可能会增加不必要的复杂性,因为getter中逻辑更改的可能性非常低,而我们所做的只是获取属性。
我希望我的问题有道理,这更多是理论上的怀疑。
修改
感谢您的回答。他们有重要的事情需要考虑。我选择的最佳答案之一是因为它引导我:
http://www.mockobjects.com/2007/04/test-smell-everything-is-mocked.html
它的真实:从理论上讲,我必须模拟Sum,这样才能成为一个纯粹的单元测试。但是对于大多数情况来说,增加复杂性的成本和模拟属性吸气剂所花费的精力并不值得获得最纯粹的"单元测试,在这种情况下实践中,单元和积分测试之间的差异是主观的。
答案 0 :(得分:5)
不要嘲笑Sum
。一般情况下,吸毒者和制定者 没有逻辑。模拟是删除一个类逻辑的过程,这样它就不会干扰另一个类的测试。模拟没有任何逻辑的类,或者逻辑与当前测试无关的类是没有意义的。事实上,"不要嘲笑价值对象"是众所周知的单元测试原理。
您的测试未使用Sum
类的任何逻辑。所以它是一个单元测试。
答案 1 :(得分:2)
但如果是这种情况并且确实是集成测试,那么我如何为ValudateMethod的validate()编写单元测试?
简单地通过
(...)模拟Sum,所以它总是返回相同的值。
集成和单元之间的界限通常很难划分。但是,让我们尝试这样做,从:
开始集成测试将测试多个组件之间的交互。
那么什么是组件?在大多数情况下 - 业务实体,一个具有运行软件所需的逻辑的类。
Sum
班怎么适合这里?它是否包含使软件运行至关重要的业务逻辑?如果是这样,如果没有嘲笑它会使你的测试整合一个(如果我们坚持上面的简单定义)。
但是,Sum
类也可以是一个存储值的类,具有很少的业务逻辑 - 如果愿意,可以使用数据结构。业务实体始终对数据结构进行操作:integers
,strings
,Points
,Addresses
- 所有数据结构,不需要进行任何集成。
分类由您和您分配给您的课程的职责决定。与数据结构交互不需要集成。与其他业务实体交互可能。