Mockito 和私有字段/注入的 bean

Mockito and private field / injected bean

accessing/setting Java-EE-Bean 中用于 Mockito 测试的私有字段的标准方法是什么?测试如下,但是MyDao-field是null,当然如果我运行(Mockito-)测试。为 MyDao 抛出 NullPointerException。

但我不想使用反射 - 有没有其他方法可以做到这一点,或者服务的架构不好?

要测试的class:

@Stateless
public class MyServiceImpl extends AbstractService {

@Inject
private MyDao myDao;

public MyEntity findByIdOrThrow( final long id ) throws Exception {
        if ( id > 0 ) {
            final MyEntity entity = myDao.findById( id );
            if ( entity == null ) {
                throw new Exception(  );
            } else {
                return entity;
            }
        } else {
            throw new Exception(  );
        }
    }

测试class:

public class MyServiceImplTest {
private MyServiceImpl myServiceImpl;

@BeforeEach
public void setup() {
    myServiceImpl = new ServiceServiceImpl();
}

@Test
public void findByIdOrThrow() throws Exception {
    Long id = 1L;
    when( myServiceImpl.findByIdOrThrow( id ) ).thenReturn( new MyEntity() );        
}}

测试class更新:

import static org.mockito.Mockito.when;

import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;

import de.myapp.dao.MyDao;
import de.myapp.entity.MyEntity;

@RunWith( MockitoJUnitRunner.class )
public class ServiceServiceImplTest {

    @Mock
    public MyDao myDao;

    @InjectMocks
    public MyServiceImpl myServiceImpl;

    @Test
    public void findByIdOrThrow() throws Exception {
        final Long id = 1L;
        when( myServiceImpl.findByIdOrThrow( id ) ).thenReturn( new MyEntity() );
    }

}

我假设 MyDao 是一个接口。您必须在测试中执行以下操作 class:

@Mock
private MyDao myDao;

@InjectMocks
private MyServiceImpl myServiceImpl;

并删除 @BeforeEach 方法。通过这种方式,您将在 te class 中注入 dao 的模拟。使用 Mockito.when 您将正确设置 dao-mock 以模拟您的真实 dao。不要忘记更改测试声明,如下所示:

@RunWith(MockitoJUnitRunner.class)
public class MyServiceImplTest

如果您使用的是 JUnit 5,测试 class 声明应如下所示:

@ExtendWith(MockitoExtension.class)
@RunWith(JUnitPlatform.class)

在最后一种情况下,您可能可以省略 @RunWith,但我不确定。