Junit:使用私有@Autowired字段

时间:2017-04-11 13:03:02

标签: java spring junit mocking integration-testing

过去几周我一直在做Junit测试,所以我作为初级程序员的经验相当有限。在测试了项目中更简单的服务类之后,现在我被卡住了 问题是我无法将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, 
    }
    /* ... */
}

以及我正在测试的服务:

@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;        
    }   
    /* ... */    
}

我的问题是,当我使用someOtherRepository.getId()运行测试null返回SpringRunner.class时。当我使用MockitoJUnitRunner.class运行时,someService构造函数会抛出构造函数错误:someRepository is NULL
我尝试了多种方式(尝试过@Spy@MockBeanMockito().doReturn...语法等),但这些是我得到的两个错误。我非常确定这是正确使用Mocking框架的问题 如果您需要其他代码段或详细信息,我将恭喜您提供。

2 个答案:

答案 0 :(得分:1)

原因是Mockito因@InjectMocks注释而尝试构造对象。

SpringRunner没有必要,因为这不是弹簧测试。如果你真的想要一个特殊的跑步者,你可以去MockitoJUnitRunner

您只需在Before方法中初始化Mockito注释,然后使用提供模拟依赖项的构造函数创建服务实例。

public class SomeServiceTest {
    @Mock
    private SomeRepository someRepository;

    private SomeService someService;

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

    /* ... */
}

答案 1 :(得分:-1)

您可以使用Spring提供的ReflectionTestUtil从测试类中注入SomeRepository的模拟。

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