【问题标题】:Junit: testing service with private @Autowired fieldsJunit:使用私有 @Autowired 字段测试服务
【发布时间】:2017-04-11 13:03:02
【问题描述】:

过去几周我一直在做 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、@MockBean、Mockito().doReturn... 语法等),但这是我得到的两个错误。我很确定这是正确使用 Mocking 框架的问题。
如果您需要其他 sn-ps 或详细信息,我会提供。

【问题讨论】:

    标签: java spring junit mocking integration-testing


    【解决方案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);
        }
    
        /* ... */
    }
    

    【讨论】:

    • 我试过了,但现在问题出在这行:Mockito.when(someService.myPrivBoolBuilder(param,-1L)) .thenReturn(new BooleanBuilder());运行时错误是when() requires an argument which has to be 'a method call on a mock'。
    • 您正在尝试模拟对真实对象 (someService) 的方法调用。你必须模拟 someRepository。
    • 你是对的。有没有什么方法可以模拟这个函数调用(比如@Spy,但也注入那个讨厌的SomeRepository)?
    • 您可以像someService = Mockito.spy(new SomeService(someRepository)) 一样进行操作。但是,请考虑一下您真正想要测试的内容,因为我认为大多数情况下将 Spy 与 Mocks 一起使用并不是一个好主意。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2015-07-26
      • 2013-05-01
      • 2015-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-19
      • 1970-01-01
      相关资源
      最近更新 更多