Unit testing 如何在隔离测试类的同时测试对象是否正确创建?

Unit testing 如何在隔离测试类的同时测试对象是否正确创建?,unit-testing,junit,tdd,mockito,Unit Testing,Junit,Tdd,Mockito,人们常说,编写单元测试时必须只测试一个类,并模拟所有协作者。我正在努力学习TDD,以使我的代码设计更好,现在我陷入了一个应该打破这条规则的境地。还是不应该 例如:被测试的类有一个方法,该方法获取人员,基于人员创建员工,并返回员工 公共类EmployeeManager{ 私人数据采集器数据采集器; 公共雇员GetCoolesEmployee(){ Person dankestPerson=dataMiner.getDankestPerson(); 员工=新员工(); setName(dankest

人们常说,编写单元测试时必须只测试一个类,并模拟所有协作者。我正在努力学习TDD,以使我的代码设计更好,现在我陷入了一个应该打破这条规则的境地。还是不应该

例如:被测试的类有一个方法,该方法获取
人员
,基于
人员
创建
员工
,并返回
员工

公共类EmployeeManager{
私人数据采集器数据采集器;
公共雇员GetCoolesEmployee(){
Person dankestPerson=dataMiner.getDankestPerson();
员工=新员工();
setName(dankestPerson.getName()+“我的代码中的错误”);
返回员工;
}
// ...
}
员工是否应被视为合作者?若否,原因为何?如果是,我如何正确测试“员工”的创建是否正确

下面是我想到的测试(使用JUnit和Mockito):

@测试
公共空冷却器员工应保存DankestPersonName(){
when(dataMinerMock.getDankestPerson()),然后return(dankPersonMock);
when(dankPersonMock.getName())。然后返回(“John Doe”);
Employee coolesteemployee=employeeManager.getcoolesteemployee();
assertEquals(“johndoe”,coolestEmployee.getName());
}
如您所见,我必须使用未经测试的
Employee
类的
coolestEmployee.getName()
-方法

我想到的一个可能的解决方案是将
Person
s转换为
Employee
s的任务提取为
Employee
类的新方法,如

公共雇员createFromPerson(个人)


我是不是想得太多了?正确的方法是什么?

单元测试的目标是快速可靠地确定单个系统是否损坏。这并不意味着你需要模拟它周围的整个世界,只是你应该确保你使用的合作者是快速的、确定的、经过良好测试的

数据对象POJO和生成的值对象尤其趋向于稳定且经过良好测试,依赖性很少。与其他有大量状态的对象一样,它们也往往很难模拟,因为模拟框架往往无法对状态进行强大的控制(例如,
getX
应该在
setX(n)
之后返回
n
)。假设Employee是一个数据对象,只要它包含的任何逻辑都经过良好的测试,它很可能是单元测试中实际使用的一个很好的候选者

一般情况下,其他合作者不得嘲笑:

  • JRE类和接口。(例如,千万不要模仿列表。它不可能被阅读,你的测试也不会对它有任何好处。)
  • 确定性第三方类。(如果任何类或方法更改为
    final
    ,您的模拟将失败;此外,如果您使用的是稳定版本的库,也不是虚假的失败源。)
  • 有状态类,只是因为mock在测试交互方面比state好得多。考虑假的,或其他一些测试加倍。< /LI>
  • 快速且经过良好测试的其他类几乎没有依赖关系。如果你对一个系统有信心,并且对你的测试的决定论或速度没有危险,就没有必要嘲笑它
剩下什么?您编写的、无状态的或在测试过程中变化很小的、可能有许多合作者的非确定性或缓慢的服务类或包装器。在这些情况下,很难使用实际的类编写一个快速且确定的测试,因此使用双重测试非常有意义,并且使用模拟框架创建一个测试非常容易


另请参见:Martin Fowler的文章,该文章讨论了各种测试双重测试及其优缺点。

单元测试的目标是快速可靠地确定单个系统是否损坏。这并不意味着你需要模拟它周围的整个世界,只是你应该确保你使用的合作者是快速的、确定的、经过良好测试的

数据对象POJO和生成的值对象尤其趋向于稳定且经过良好测试,依赖性很少。与其他有大量状态的对象一样,它们也往往很难模拟,因为模拟框架往往无法对状态进行强大的控制(例如,
getX
应该在
setX(n)
之后返回
n
)。假设Employee是一个数据对象,只要它包含的任何逻辑都经过良好的测试,它很可能是单元测试中实际使用的一个很好的候选者

一般情况下,其他合作者不得嘲笑:

  • JRE类和接口。(例如,千万不要模仿列表。它不可能被阅读,你的测试也不会对它有任何好处。)
  • 确定性第三方类。(如果任何类或方法更改为
    final
    ,您的模拟将失败;此外,如果您使用的是稳定版本的库,也不是虚假的失败源。)
  • 有状态类,只是因为mock在测试交互方面比state好得多。考虑假的,或其他一些测试加倍。< /LI>
  • 快速且经过良好测试的其他类几乎没有依赖关系。如果你对一个系统有信心,并且对你的测试的决定论或速度没有危险,就没有必要嘲笑它
剩下什么?您编写的、无状态的或在测试过程中变化很小的、可能有许多合作者的非确定性或缓慢的服务类或包装器。在这些情况下,很难使用实际的类编写快速且确定的测试,因此使用测试doub非常有意义