mockito applicationContext的Junit测试用例,getBean(类别)传回空值

66bbxpm5  于 2022-11-08  发布在  其他
关注(0)|答案(2)|浏览(1410)

当试图为applicationContext.getBean(classname)编写测试用例时.获取空指针异常.下面是Java类

@Service
@Slf4j
public class MyClassName {

  @Autowired
  ServiceOne serviceOne;

  @Autowired
  ApplicationContext applicationContext;

  public getCitizenData(String mobileNumber) {

    CitizenDataService citizenDataService = applicationContext.getBean(CitizenDataService.class, mobileNumber);
    log.info("Getting Data");
    return citizenDataService.searchMethod(mobileNumber)
         // While debugging test file citizenDataService is coming as Null Hence getting Null Pointer exception
        .flatMap(.............
         )

测试文件

class MyClassNameTest {

  private MyClassName mockMyClassName;

  @BeforeEach
  void setUp() {
    mockMyClassName = new MyClassName();
    mockMyClassName.serviceOne = mock(ServiceOne.class);
    mockMyClassName.applicationContext = mock(ApplicationContext.class);
    //mockMyClassName.applicationContext.getAutowireCapableBeanFactory();
  }

  @Test
  void testGetCitizenData() {
    // Setup
    // Configure ApplicationContext.getBean(...).
    final CitizenDataService citizenDataService = new CitizenDataService("mobileNumber");
    when(mockMyClassName.applicationContext.getBean(CitizenDataService.class, "args"))
        .thenReturn(citizenDataService);

    final result = mockMyClassName.getCitizenData("mobileNumber");
    // While debugging this citizenDataService is coming as Null Hence getting Null Pointer exception

如何编写测试用例?

bmvo0sr5

bmvo0sr51#

这是因为您在mock的ApplicationContext上存根了不正确的参数。当mock上的一个方法被调用,但没有匹配的存根参数时,它将返回null或空集合,或者默认情况下,对于int/Integer返回0,对于boolean/Boolean返回false。所以在您的情况下,返回NULL CitizenDataService
更改以下内容应该可以解决您的问题:

when(mockMyClassName.applicationContext.getBean(CitizenDataService.class, "mobileNumber"))
    .thenReturn(citizenDataService);

另一种方法是不模拟ApplicationContext,而是使用spring测试来真正启动spring容器,其中包含测试用例所需的bean:

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {MyClassName.class,ServiceOne.class,CitizenDataService.class})
public class MyClassNameTest {

     @Autowired
     private MyClassName myClassName

      @Test
      void testGetCitizenData() { 

     }

}

这将比普通的Mockito方法慢,因为它需要更多的时间来启动Spring容器,并且还需要您管理要在上下文中包含哪些bean。
对我来说,我会重构你的类,这样它就不需要自动连接ApplicationContext,然后写一个普通的Mockito测试。手动从ApplicationContext获取bean不是一个好的做法,这会使你的类耦合到spring框架代码。

tnkciper

tnkciper2#

我不建议模仿应用程序上下文。有太多的方法具有相似的参数,很难模仿正确的参数。相反,使用一个现成的、专门为测试而编写的实现,比如StaticApplicationContext

class MyClassNameTest {
  private MyClassName mockMyClassName;
  private ApplicationContext appCtx;

  @BeforeEach
  void setUp() {
    mockMyClassName = new MyClassName();
    mockMyClassName.serviceOne = mock(ServiceOne.class);
    this.appCtx = new StaticApplicationContext();
  }

  @Test
  void testGetCitizenData() {
    appctx.registerBean(CitizenDataService.class, () -> new CitizenDataService("mobileNumber"));

    final result = mockMyClassName.getCitizenData("mobileNumber");

相关问题