当前位置: 首页 > 知识库问答 >
问题:

如何使用Mockito模拟spring应用程序上下文创建的对象以实现单元测试覆盖率?

孟谭三
2023-03-14

应用场景: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是一个带有服务注释的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的模拟对象并成功运行测试用例。如何模拟或监视Application ationContextUtils,以便Load任务不会抛出任何错误?

共有1个答案

程俊誉
2023-03-14
@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内联依赖项

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.10.0</version>
    <scope>test</scope>
 </dependency>
 类似资料:
  • 问题内容: 当我创建一个说类Employee的模拟对象时。它不调用Employee对象的构造函数。我知道Mockito在内部使用CGLIb和反射,创建了一个代理类,将该类扩展为模拟。如果未调用employee的构造函数,那么如何创建employee类的模拟实例? 问题答案: Mockito使用CGLib生成类对象。但是,要实例化此类对象,它使用Objenesis http://objenesis.

  • 为了获得可重用和可测试的rxjava代码,我使用ObservableTransformers分离了代码的各个部分。它在生产中工作得很好,但是测试它并不像预期的那么容易,因为我似乎无法模拟那些观察到的ransformers。 when(observableTransformer.apply(any())).thenreturn(observable.just(“mockedtext”)); 一旦调用

  • 我有一个问题与存根我的存储库。有人建议我只创建另一个application.properties(我没有这样做),并使用像H2这样的内存数据库。不过,我想知道我是否可以只是存根调用,这样当调用MyDataService.FindById(id)而不是试图从数据库中获取它时,就可以返回一个模拟对象?

  • 我们在dropwizard应用程序中有一个配置类: 我需要通过读取yaml文件在单元测试中创建真正的配置对象。有什么指针会有用吗? 看起来像是当dropwizard应用程序启动时,应用程序将读取yaml配置文件并创建MyConfiguration,但是在运行简单的单元测试时,我想要一个真实的(不是模拟的)配置对象。 谢谢你。

  • 我正在为以下类编写单元测试 要测试的类: 注意:我正在使用TestNG和mockito。我可以扩展并使用,声明我的bean和自动应用上下文。我觉得这对我的用例来说是矫枉过正。我只需要模拟ApplicationContext的getBean方法。

  • 问题内容: 我知道关于模拟和测试有很多问题,但是我发现没有任何问题可以完美地帮助我,因此我仍然对理解以下内容有疑问: 如果我弄错了,请纠正我,但据我所知,单元测试用于隔离测试一个特定类的业务逻辑,并且如果有外部需要的任何对象,它们将被模拟。因此,例如,如果我有一个简单城市居民的管理系统,该系统将居民添加到列表中并按姓名返回居民(假设:居民仅包含一些基本个人信息),如下所示: 如果现在我要进行单元测