模拟具有许多依赖项的嵌套服务 类

Mocking nested service classes with many dependencies

我有一堆服务 classes,它们看起来都很像这个或类似的。

@Service
public class ServiceA {
   private RepositoryA repA;
   private RepositoryB repB;
   private DependencyC depC;
   private DependencyD depD;
   private ServiceB serviceB;

   @Autowired
   public ServiceA(RepositoryA repA, RepositoryB repB, DependencyC depC, DependencyD depD, ServiceB serviceB) {
        this.repA = repA;
        ....
   }
}

现在我想在我的测试 classes 中使用这些服务而无需启动 Spring。如果我在应用程序上下文中使用 beans,测试将花费太长时间。我想模拟服务 classes,但由于嵌套结构很深,我不知道该怎么做。简单的方法是模拟 ServiceA 使用的所有存储库、依赖项和服务,然后自己将它们注入到测试中 class 但这似乎不对,因为我必须对 ServiceB 做同样的事情。

对偶选择:

  1. 也模拟ServiceB
  2. 按照您的描述进行操作,因为无论如何您都会这样做,以便为 ServiceB 编写测试,这样您就可以重用该工作
  3. 构建一个充满模拟的替代Spring上下文并将其用于测试

我通常选择 2。它是不纯的,因为 ServiceA 的正确性取决于 ServiceB 的正确性,但它较少测试编写、管理和理解的代码。

你可以为此使用 mockito,那么你的代码将与此类似

@RunWith(MockitoJUnitRunner.Silent.class)
public class ServiceATest {

   @Mock
   RepositoryA repA;

   @Mock
   RepositoryB repB;

   @Mock
   DependencyC depC;

   @Mock
   DependencyD depD;

   @Mock
   ServiceB serviceB;

   @InjectMocks
   ServiceA serviceA;
}

然后,当你需要在你的测试中使用模拟时,你模拟你模拟的方法类,例如:

@Test
public void someTest() {
  ...
  when(repA.repMethod()).thenReturn(new SomeObject());
  
  SomeObject mockedObject = serviceA.serviceMethod(); // if serviceMethod call repMethod, you will get the object which you passed in youк mock method call
  ...
}
public class ServiceATest {
   private RepositoryA repA;
   private RepositoryB repB;
   private DependencyC depC;
   private DependencyD depD;
   private ServiceB serviceB;

    @Before
    public void init() { 
    this.repB = mock(RepositoryA.class);
     .....
    // mock all repositories you need.
    this.serveceB = new ServiceB(repoB,...);
    //then use contructor method to instantiate serviceB. Also do same with 
    //serviceB 
    this.serviceA = new ServiceA(repA,  repB,depC, depD, serviceB)
    }



     //Write the tests like that

     @Test
     public void saveanything_shouldBeCorect() {
     when(repoA.save()any()).thenReturn(mySavedMock);
     MyVariable resp = serviceA.save(myMock);
     // them assert your resp.
     }
    

}

重要的是仅在已移动到 init 方法的存储库中使用 mockito 方法“when (rep.anython (any ()))。