单元测试如何使用Mockito模拟存储库

Dan*_*ani 1 java unit-testing mocking mockito spring-boot

我存根我的存储库时遇到问题。建议我只创建另一个application.properties(我尚未完成),并使用内存数据库(例如H2)。我想知道是否可以仅对调用进行存根处理,以便在调用myDataService.findById(id)而不是尝试从数据库中获取它时,可以返回模拟对象吗?

一般来说,我是为单元测试和Spring Boot编写模拟游戏的新手,所以也许我错过了一些东西。以下代码(为简化起见,使名称通用,可在此处发布)。

我的考试课

public class MyServiceImplTest 
{
    private MyDataService myDataService;
    private NyService myService;
    private MyRepository myRepository;

    @Before
    public void setUp() {
        myDataService = Mockito.mock(MyDataServiceImpl.class);
        myService = new MyServiceImpl(myDataService);
    }

    @Test
    public void getById_ValidId() {
        doReturn(MyMockData.getMyObject()).when(myDataService).findById("1");
        when(myService.getById("1")).thenReturn(MyMockData.getMyObject());
        MyObject myObject = myService.getById("1");

        //Whatever asserts need to be done on the object myObject 
    }
}
Run Code Online (Sandbox Code Playgroud)

用于对数据层进行服务调用的类

@Service
public class MyServiceImpl implements MyService {
    MyDataService myDataService;

    @Autowired
    public MyServiceImpl(MyDataService myDataService) {
        this.myDataService = myDataService;
    }

    @Override
    public MyObject getById(String id) {
        if(id == null || id == "") {
            throw new InvalidRequestException("Invalid Identifier");
        }

        MyObject myObj;
        try {
            myObj = myDataService.findById(id);
        }catch(Exception ex) {
            throw new SystemException("Internal Server Error");
        }

        return myObj;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我测试中遇到的问题。调用findById()方法时,变量存储库为null,因此在尝试执行repository.findOne(id)时会抛出异常。这是我试图模拟的内容,但是存储库给了我一些问题。

@Repository
@Qualifier("MyRepo")
public class MyDataServiceImpl {

    @PersistenceContext
    private EntityManager em;

    private MyRepository repository;

    @Autowired
    public MyDataServiceImpl(MyRepository repository) {
        super(repository);
        this.repository = repository;
    }

    public MyObject findById(String id) {
        P persitentObject = repository.findOne(id);
        //Calls to map what persitentObject holds to MyObject and returns a MyObject 
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的MyRepository代码只是显示它是扩展CrudRepository的空接口

public interface MyRepository extends CrudRepository<MyObjectPO, String>, JpaSpecificationExecutor<MyObjectPO> {

}
Run Code Online (Sandbox Code Playgroud)

pvp*_*ran 5

首先,我要说明的是,使用构造函数注入而不是字段注入使您处在正确的轨道上(这使使用模拟编写测试变得更加简单)。

public class MyServiceImplTest 
{
    private MyDataService myDataService;
    private NyService myService;

    @Mock
    private MyRepository myRepository;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this); // this is needed for inititalizytion of mocks, if you use @Mock 
        myDataService = new MyDataServiceImpl(myRepository);
        myService = new MyServiceImpl(myDataService);
    }

    @Test
    public void getById_ValidId() {

        doReturn(someMockData).when(myRepository).findOne("1");
        MyObject myObject = myService.getById("1");

        //Whatever asserts need to be done on the object myObject 
    }
}
Run Code Online (Sandbox Code Playgroud)

该调用从您的服务-> dataService一直进行。但是只有您的存储库调用是模拟的。
这样,您可以控制和测试类的所有其他部分(服务和数据服务),并且仅模拟存储库调用。