简体   繁体   English

Junit:使用@Autowired专用字段进行测试服务

[英]Junit: testing service with private @Autowired fields

I have been doing Junit tests the past few weeks so my experience, being a junior programmer is fairly limited. 我过去几周一直在进行Junit测试,因此,作为一名初级程序员,我的经验非常有限。 After testing the easier service classes in the project, now I am stuck. 在测试了项目中较简单的服务类之后,现在我陷入了困境。
The problem is that I can't inject some private final someRepository into the constructor of the service class that I am testing, namely: 问题是我无法将一些private final someRepository注入到我正在测试的服务类的构造函数中,即:

@RunWith(SpringRunner.class)
public class SomeServiceTest {
    @Mock
    private SomeRepository someRepository;
    @InjectMocks
    private SomeService someService;

    @Test
    public void testMyFunc() {
        SomeOtherDto param = new SomeOtherDto();
        param.setVar1(...);
        param.setVar2(...);
        Mockito.when(someRepository.getIt()).thenReturn(-1L);
        Mockito.when(someService.myPrivBoolBuilder(param,-1L))                                                                                     
                                             .thenReturn(new BooleanBuilder());
        Pageable pageable = null;
        Page<SomeDto> result = someService.myFunc(param, pageable);
        assertEquals(expResult, 
    }
    /* ... */
}

and the service I am testing: 以及我正在测试的服务:

@Service
@Transactional
public class SomeService implements someAbstractService {
    private final CustomMapper customMapper
    private final SomeRepository someRepository;
    private final SomeOtherRepository someOtherRepository;

    @Autowired
    public SomeService(final CustomMapper customMapper, final SomeRepository someRepository, 
                       final SomeOtherRepository someOtherRepository, etc) 
    { /* ... */ }

    public Page<SomeDto> myFunc(final SomeOtherDto param, final Pageable pageable) {
        final BooleanBuilder predicate = myPrivBoolBuilder(param, 
                                             someOtherRepository.getId());  
        return someRepository.findAll(predicare, pageable).map(obj -> {  
                                             return customMapper.map(obj) });
    }

    public BooleanBuilder myPrivBoolBuilder(final SomeOtherDto param, final Long id) {
        BooleanBuilder predicate = new BooleanBuilder();
        final QSomeRepository qSomeRepository = QSomeRepository.someRepository;
        final QSomeOtherRepository qSomeOtherRepository  = QSomeOtherRepository.someOtherRepository();
        predicate.and(qSomeRepository.someField.someOtherField.goe(param.getX()));
        predicate.and(qSomeRepository.someField2.someOtherField2.isNotNull()));
        predicate.and(qSomeOtherRepository.someField.someOtherField.id.eq(id()  
            .or(qSomeOtherRepository.someField.someOtherField.id.in(...))));
        return predicate;        
    }   
    /* ... */    
}

My problem is that when I run the test someOtherRepository.getId() return null with SpringRunner.class . 我的问题是,当我运行测试时, someOtherRepository.getId()使用SpringRunner.class返回null When I run with MockitoJUnitRunner.class the someService constructor throws a constructor error: someRepository is NULL 当我使用MockitoJUnitRunner.class运行时, someService构造函数将引发构造函数错误: someRepository is NULL
I have tried multiple ways (tried @Spy , @MockBean , Mockito().doReturn... syntax, etc), but these are the two errors I get. 我尝试了多种方法(尝试了@Spy@MockBeanMockito().doReturn...语法等),但这是我遇到的两个错误。 I'm pretty sure it's a matter of using the Mocking framework correctly. 我很确定这是正确使用Mocking框架的问题。
If you need other snippets or details, I will kindly offer them. 如果您需要其他代码段或详细信息,请提供。

The reason is that Mockito tries to construct the object because of the @InjectMocks annotation. 原因是由于@InjectMocks批注,Mockito试图构造对象。

SpringRunner is not necessary as this is not a spring test. SpringRunner因为这不是弹簧测试。 If you really want a special runner, you can go for MockitoJUnitRunner . 如果您真的想要一个特殊的跑步者,可以选择MockitoJUnitRunner

You can simply initialize the Mockito annotations in your Before method and then create your service instance with the constructor providing the mocked dependencies. 您可以简单地在Before方法中初始化Mockito批注,然后使用提供模拟依赖项的构造函数创建服务实例。

public class SomeServiceTest {
    @Mock
    private SomeRepository someRepository;

    private SomeService someService;

    @Before
    public void setUp() {
         MockitoAnnotations.initMocks(this);
         someService = new SomeService(someRepository);
    }

    /* ... */
}

You could use ReflectionTestUtil provided by Spring to inject a mock of SomeRepository from the test class. 你可以使用ReflectionTestUtil Spring提供从测试类注射SomeRepository的模拟。

eg; 例如; ReflectionTestUtils.setField(someService, "someRepository", mock(SomeRepository.class));

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

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