【问题标题】:How to mock object created by spring application context using Mockito for Unit Test coverage?如何使用 Mockito 模拟由 Spring 应用程序上下文创建的对象以进行单元测试覆盖?
【发布时间】:2021-05-10 12:45:16
【问题描述】:

应用场景: TaskScheduler 以定期 cron 间隔触发。每个调度程序作业将创建多个可运行线程。每个线程都会执行 ETL 过程。

public class LoadTask {

    private static final AuditLogService AUDIT_LOG_SERVICE = 
    ApplicationContextUtils.getApplicationContext().getBean("auditLogService", AuditLogService.class);

    public void perform(ETLDetailsDTO etlDetailsDTO) {
       // Business logic
       AUDIT_LOG_SERVICE.save(AuditLogBuilder.buildSuccessAuditLog())
   }
}

AuditLogService 是一个 Service 注解的 Spring 托管 bean。

@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    @Getter
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext appContext) {
        applicationContext = appContext;
    }
}

LoadTask 不是 Spring 托管组件,因此我借助 ApplicationContextUtils 来获取 AuditLogService 的 bean。该应用程序运行良好。在编写LoadTask的单元测试用例时,抛出空指针异常。

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class LoadTaskTest {

@InjectMocks
private LoadTask loadTask;

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
}

@Test
public void testPerform() {
    Mockito.when(ApplicationContextUtils.getApplicationContext().getBean("auditLogService", AuditLogService.class)).thenReturn(new AuditLogService());
    loadTask.perform(MockObjectHelper.getETLDetailsDTO());
}
}

我无法设置 AUDIT_LOG_SERVICE 的模拟对象并成功运行测试用例。如何 mock 或 spy ApplicationContextUtils 使 LoadTask 不会抛出任何错误?

【问题讨论】:

    标签: java spring unit-testing mockito applicationcontext


    【解决方案1】:
    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    public class LoadTaskTest {
    
    @InjectMocks
    private LoadTask loadTask;
    @Mock
    private ApplicationContext applicationContext;
    @Mock
    private AuditLogService auditLogService;
    
    @BeforeEach
    public void setUp() {
        MockitoAnnotations.openMocks(this);
        new ApplicationContextUtils().setApplicationContext(applicationContext);
    }
    
    @Test
    public void testPerform() {
        Mockito.when(applicationContext.getBean("auditLogService", AuditLogService.class)).thenReturn(auditLogService);
        loadTask.perform(MockObjectHelper.getETLDetailsDTO());
     }
    }
    

    添加 mockito-inline 依赖

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-inline</artifactId>
        <version>3.10.0</version>
        <scope>test</scope>
     </dependency>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-06
      • 1970-01-01
      • 1970-01-01
      • 2011-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多