【问题标题】:Mockito - Mock a method inside async method that is under testMockito - 在正在测试的异步方法中模拟一个方法
【发布时间】:2020-12-24 23:50:00
【问题描述】:

您好,我正在尝试使用异步方法进行一些单元测试。下面是我的代码。我嘲笑 doWork 的第一行 methodUnderTest() 在执行期间返回 null 并且测试失败。我尝试了与异步相关的不同方法,但没有任何效果。我在这里错过了什么。

 public class AServiceImpl{
   @Autowired
   BService bService;

   @Async
   public CompletableFuture<String> methodUnderTest(String input){
     String s = bService.doWork(input.substring(3));
     //blah blah blah
     return CompletableFuture.completedFuture(s);
   }
}


public class AServiceTest{
  private BService bService;
  private AService aService;
  @Before
  void beforeTest(){
     aService = new AServiceImpl();
     bService = mock(BService.class);
     //blah blah blah
  }

  @Test
  public void someUnitTest(){
     Mockito.when(bService.doWork(any())).thenReturn("ABC");
     String s = aService.methodUnderTest("ABCDEF").get();
     Assert.assertNotNull(s);
  }
}

【问题讨论】:

    标签: spring mockito


    【解决方案1】:

    这里与@Async 无关。测试中的模拟设置未分配给被测对象。

    首先,我建议避免使用 Autowired 字段,并让您的类通过构造函数依赖项显式公开它们的依赖项

    public class AServiceImpl {
        
        private final BService bService;
    
        @Autowired
        public AServiceImpl(BService bService) {
            this.bService = bService;
        }
    
        @Async
        public CompletableFuture<String> methodUnderTest(String input) {
            String s = bService.doWork(input.substring(3));
    
            //...
    
            return CompletableFuture.completedFuture(s);
        }
    }
    

    然后在测试时显式注入依赖

    public class AServiceTest{
        private BService bService;
        private AService aService;
    
        @Before
        void beforeTest() {
            bService = mock(BService.class);
            aService = new AServiceImpl(bService); //<-- injecting mocked dependency
    
            //...
        }
    
        @Test
        public void someUnitTest(){
            // Arrange
            Mockito.when(bService.doWork(any())).thenReturn("ABC");
            // Act
            String s = aService.methodUnderTest("ABCDEF").get();
            // Assert
            Assert.assertNotNull(s);
        }
    }
    

    【讨论】:

      【解决方案2】:

      您的自动接线仅适用于生产代码。您需要在测试中手动注入您的模拟 BService

      @Before
      void beforeTest() {
          aService = new AServiceImpl();
          bService = mock(BService.class);
          aService.bService = bService;
          ...
      }
      

      您可以使用 @RunWith(SpringRunner.class) (JUnit 4) 或 @ExtendWith(SpringExtension.class) (Junit 5) 使用 spring 运行测试以注入测试依赖项。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多