text: 我们写单元测试用的是JUnit，Java实际意义上的标准测试框架。我们使用Mockito来打桩隔离掉真正的PersonRepository类。这个桩允许我们在测试里重新定义PersonRepository被调用后产生的响应。桩能让我们的测试更简单，更可预测，更容易组织测试数据。
  依照Arrange，Act，Assert的结构，我们写了两个单元测试：一个是正常的场景，另一个是找不到搜索人的场景。首先，正常场景创建了一个新的person对象，然后告诉mock类，当你接受到以“Pan”作为参数的调用时，返回这个person对象。这个测试接着调用了被测试方法。最后它断言返回值是等于期待结果的。
  第二个测试和第一个类似，但它测试的是被测方法找不到对应人名时的场景。
  所有常见的应用都会和一些外部环境做集成（数据库，文件系统，向其他应用发起网络请求）。为了使测试有更好的隔离、运行更快，我们通常不会在编写单元测试时涉及这些外部依赖。不过，这些交互始终是存在的，它们也需要被测试覆盖到。这正是集成测试的用处所在。它们测试的是应用与所有外部依赖的集成。
  对于自动化测试来说，不仅需要运行自己的应用，也需要运行与之集成的组件。如果要测试和数据库的集成，那就需要在跑测试的时候运行数据库。如果要测试能否从硬盘里读取文件，就需要先保存一个文件到硬盘上，然后在集成测试中去读取它。
  前面我提到过「单元测试」是一个模煳的术语，对于集成测试而言，更是如此。对于一些人来讲，集成测试意味着去测试和多方应用产生交互的整个应用。我理解的集成测试更加狭义：每次只测试一个集成点。测试时应使用测试替身来替代其他的外部服务、数据库等。同时，使用契约测试对测试替身和真实实现进行覆盖。这样出来的集成测试更快，更独立，更易理解和调试。
  狭义的集成测试测的是服务的边界。从概念上来说，这样的测试总是在触发导致应用和外部依赖（文件系统，数据库，其他服务等）集成的行为。比如说，一个数据库集成测试可能会这么写：
  (一个集成了你的代码和数据库的集成测试)
  另一个例子，一个通过RESTAPI和外部服务集成的测试可能是会这么写:
  (这种集成测试检查了应用是否能正确和外部服务通信)
  代码中所有涉及数据序列化和反序列化的地方都要写集成测试。这些场景可能比你想象得更多，比如说：
  为这些边界编写集成测试，保证了对外部系统的数据读写操作是正常工作的。
  在测试金字塔中，集成测试的层级比单元测试更高。集成缓慢的外部依赖（如文件系统或数据库等）通常比隔离了这些依赖的单元测试需要更长时间。他们可能比小型并且独立的单元测试难写，毕竟你需要让外部依赖在你的测试中运行起来。然而，它的优势在于建立了你对应用能正确访问外部依赖的自信，这是单纯的单元测试做不到的。
  PersonRepository是代码里唯一的数据库类。它依赖于SpringData，我们并没有实际去实现它。只需要继承CrudRepository接口并声明一个方法名。剩下的就是Spring魔法了，Spring会帮我们实现其他所有的东西。