【问题标题】:JUnit and Mockito returns null while mockingJUnit 和 Mockito 在模拟时返回 null
【发布时间】:2018-10-29 07:31:08
【问题描述】:

我对 JUnit 和 Mockito 完全陌生。我在测试我的ServiceImpl 课程时遇到了问题。 当调试时指针进入ServiceImpl 类时,该方法会抛出nullPointerException。 谁能告诉我如何在“getDetails”方法中调用该方法。 "varNumber" 总是返回 null。

DetailsUtilsClientImpl 类

  private final DetailsUtils detailsUtils;

  @Autowired
  Utils utils

 @Autowired
 public DetailsUtilsClientImpl( DetailsUtils 
 detailsUtils) {
    this.detailsUtils= detailsUtils;
}

    public Details getDetails( String var1 ) {
       String varNumber = utils.smgContent( var1 ); 
       Details getDetailsDocument =
       detailsRepository.findById( varNumber ).orElse( null );
    return null;
}

测试类

@Autowired
DetailsUtils detailsUtils;

@Autowired
DetailsUtilsClient detailsUtilsClient;

@Autowired
Utils utils

@Autowired
Pageable pageable;

 @Before
public void setUp() {
    detailsUtils = mock( DetailsUtils.class );
    utils = mock( Utils.class );
    pageable = mock( Pageable.class );
}

@Test
public void getCarDocument() {

    List<Entity.Type> listPre = new ArrayList<Entity.Type>();
    Entity.Type preTest = new Entity.Type();
    preTest.setDesc( Mob.AUTOMOB );
    preTest.setDet( Car.CAR );
    listPre.add( preTest );

    Entity c1 = new Entity();
    c1.setId( "accountID" );
    c1.setCarNo( "gfsd2134gh" );
    c1.setCarDetail( "accountDet" );
    c1.setEntity( listPre );

    detailsUtilsClient client =
        new DetailsUtilsClientImpl( detailsUtils );


    Optional<Entity> client1 = Optional.of( c1 );
    when( detailsUtils.findById( c1.getCarNo() ) ).thenReturn( client1 );
    Entity c2 = client.getEntity ( "gfsd2134gh" );
    assertThat( c2.getCarNo(), equalTo( c1.getCarNo() ) );
   }

【问题讨论】:

  • 你的测试类没有测试甚至没有使用ServiceImpl。它测试 DetailsUtilsClientImpl.getEntity()。
  • 对不起。这是DetailsUtilsClientImpl。不是 ServiceImpl。

标签: java spring-boot junit mockito


【解决方案1】:

永远不要使用 @Autowired 来模拟依赖,而是使用 @Mock 来模拟依赖。 @InjectMocks 将创建对象并注入所有模拟的依赖项。 在单元测试中,我们基本上关注的是方法的工作和依赖关系之间的交互。 http://www.startwithjava.com/best-practices-for-unit-testing/

public class Test{

    @Mock
    DetailsUtils detailsUtils;

    @InjectMocks
    DetailsUtilsClient detailsUtilsClient;

    @Mock
    Utils utils;

    @Mock
    Pageable pageable;


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

    @Test
    public void getCarDocument() {
        //GIven
        List<Entity.Type> listPre = new ArrayList<Entity.Type>();
        Entity.Type preTest = new Entity.Type();
        preTest.setDesc( Mob.AUTOMOB );
        preTest.setDet( Car.CAR );
        listPre.add( preTest );

        Entity c1 = new Entity();
        c1.setId( "accountID" );
        c1.setCarNo( "gfsd2134gh" );
        c1.setCarDetail( "accountDet" );
        c1.setEntity( listPre );


        Optional<Entity> client1 = Optional.of( c1 );
        when( detailsUtils.findById( c1.getCarNo() ) ).thenReturn( client1 );

        //When
        Entity c2 = detailsUtilsClient.getEntity ( "gfsd2134gh" );

        //Then
        assertThat( c2.getCarNo(), equalTo( c1.getCarNo() ) );
        //use behavior test using Mockito.verify(dependency,times(noOfInteraction)).methodName(arg)
        Mockit.verify(detailsUtils,Mockito.times(1))..findById( c1.getCarNo() );
       }

    }

【讨论】:

  • 感谢您的回答。我仍然在 ServiceImpl 类中的 String varNumber = utils.smgContent( var1 ); 处收到 NullPointerException。
  • String varNumber = utils.smgContent( var1 ); 行的 Impl 类中,我得到了 var1 的值,但 utils 的值为 null。
  • 在一个服务类测试中,您只需测试该服务类方法。不是依赖类的方法。只需要验证它们之间的交互。
  • 所有的模拟依赖都是代理对象,我们使用 when 和 thenReturn 提供模拟实现。
  • 但是在服务类方法中,我从不同的类中调用了不同的方法。那么对于utils.smgContent,我应该写whenthen吗?
【解决方案2】:

NPE 通常是由于测试用例配置错误而发生的,而您省略了最“有意义”的部分 - 测试用例配置:

如果您使用@Autowired,您可能会尝试使用spring(否则它没有意义)。但在这种情况下,测试应该使用特殊的 spring 运行器运行,它将启动应用程序上下文,初始化所有 bean,然后将它们自动装配到测试字段。

至少应该是@RunWith(SpringRunner.class)

在这种情况下,它不再是单元测试,而更像是集成/组件测试。

或者,如果您根本不想使用 Spring,那么必须有人实例化这些类。这是一个常规的单元测试。

JUnit 作为工具默认不能实例化任何东西。

因此,您必须“指导”JUnit 关于这一点。由于您在这里使用 Mockito,可能您应该使用规则或运行器(指导 junit - mockito 集成):

规则方法:

 class ExampleTest {
   @Rule
   public MockitoRule rule = MockitoJUnit.rule();
 }

跑步者方法:

 @RunWith(MockitoJUnitRunner.class)
 public class ExampleTest {
 }

【讨论】:

  • 即使有@RunWith(MockitoJUnitRunner.class) 我在ServiceImpl 类中也得到NullPointerException。我从@Autowired 更改为@Mock
  • 这里要调试。你甚至没有向我们展示一个 ServiceImpl 类,你也没有直接在测试中使用它,所以这里很难说更具体的东西。
  • 我已经更新了我的 Impl 类。当我调试时,我在Utils utils 得到null
猜你喜欢
  • 1970-01-01
  • 2021-05-08
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多