简体   繁体   English

JUnit和Mockito在模拟时返回null

[英]JUnit and Mockito returns null while mocking

I'm completely new to JUnit and Mockito. 我对JUnit和Mockito完全陌生。 I'm facing problem while testing my ServiceImpl class. 我在测试ServiceImpl类时ServiceImpl问题。 When the pointer goes inside the ServiceImpl class while debugging, the method throws nullPointerException . 当指针在调试时进入ServiceImpl类内部时,该方法将抛出nullPointerException Could anyone please tell me how to invoke the method inside "getDetails" method. 谁能告诉我如何在“ getDetails”方法中调用该方法。 "varNumber" always returns null. “ varNumber”始终返回null。

DetailsUtilsClientImpl class 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;
}

Test class 测试班

@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() ) );
   }

Never use @Autowired for dependency rather use @Mock for the dependency to mock. 切勿使用@Autowired进行依赖,而应使用@Mock进行模拟。 @InjectMocks will create object and inject all the mocked dependencies. @InjectMocks将创建对象并注入所有模拟的依赖项。 In Unit testing, we are basically concern about the working of a method and interaction between the dependency. 在单元测试中,我们基本上关注方法的工作以及依赖之间的交互。 http://www.startwithjava.com/best-practices-for-unit-testing/ 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() );
       }

    }

Usually NPEs happen due to a wrong configuration of the test case, and you've omitted the most "meaningful" part - a test case configuration: 通常,NPE的发生是由于测试用例的配置错误,因此您省略了最“有意义的”部分-测试用例配置:

If you use @Autowired , the chances are that you try to use spring (otherwise it doesn't make sense). 如果使用@Autowired ,则有可能尝试使用spring(否则就没有意义)。 But in this case, the test should be run with a special spring runner that will start the application context, init all the beans and then autowire them to the test fields. 但是,在这种情况下,应该使用特殊的SpringRunner来运行测试,该启动器将启动应用程序上下文,初始化所有bean,然后将它们自动连接到测试字段。

At least it should be @RunWith(SpringRunner.class) 至少应该是@RunWith(SpringRunner.class)

In this case it's not a unit-test anymore, but more like an integration/component test. 在这种情况下,它不再是单元测试,而更像是集成/组件测试。

Alternatively, if you don't want to use Spring at all, then someone has to instantiate the classes. 另外,如果您根本不想使用Spring,则必须有人实例化这些类。 This is a regular unit test. 这是常规的单元测试。

JUnit as a tool by default can't instantiate anything. 默认情况下,JUnit作为工具无法实例化任何内容。

So, you have to "instruct" JUnit about this. 因此,您必须对此“指导” JUnit。 Since you're using Mockito here, probably you should use a rule or runner (instruct about junit - mockito integration): 由于您在此处使用Mockito,可能应该使用规则或运行器(指导junit-Mockito集成):

Rule approach: 规则方法:

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

Runner approach: 跑步者方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM