【问题标题】:Mocking nested service classes with many dependencies模拟具有许多依赖项的嵌套服务类
【发布时间】:2021-04-14 15:36:43
【问题描述】:

我有一堆服务类,看起来都差不多,或者类似。

@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;
        ....
   }
}

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

【问题讨论】:

  • 您为什么需要使用ServiceB 来执行此操作?这也应该是这个类的一个模拟。

标签: java spring mockito


【解决方案1】:

您可以为此使用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
  ...
}

【讨论】:

    【解决方案2】:

    几个选择:

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

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

    【讨论】:

      【解决方案3】:
      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 ()))。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-24
        • 1970-01-01
        • 2020-03-28
        • 1970-01-01
        • 1970-01-01
        • 2017-09-30
        • 2012-11-15
        相关资源
        最近更新 更多