模拟对象,数据库访问对象和事务范围

时间:2016-03-09 17:04:00

标签: java unit-testing transactions mocking graph-databases

我使用easy mock来测试我的一些课程。它们是非常简单的微服务;他们从队列中读取消息(顶点id)并调用方法。此方法打开一个事务,访问图数据库中的顶点,对该顶点执行一些操作,最后关闭该事务。

以下是一个示例方法:

public void updateLocation(String s) {
    ReadWriteTransaction tx = GraphHolder.readWriteTransaction();
    tx.commit(() -> {
        User user = UserFactory.getUser(s, tx);
        if (user != null) {
            Location approxLocation = getMapApi().getLocationFromPhoneNumber(user.getPhone())
            user.setLocation(approxLocation);
        }
    });
}

这依赖于外部API,应该被嘲笑。我使用的是EasyMock,因此设置看起来有点像这样:

public MapApi getMockedMapApi() {
    ReadWriteTransaction tx = GraphHolder.readWriteTransaction();
    return tx.commit(() -> {
        Location location = LocationFactory.createLocation(tx);
        location.setCity(CITY);
        MapApi mapApi = createMock(MapApi.class);
        expect(mapApi.getLocationFromPhoneNumber(PHONE_NUMBER)).andReturn(location);
        replay(mapApi);
        return mapApi;
    });
}

此方法的问题在于,位置对象存在于与用户对象不同的事务范围中。访问或更改事务范围之外的任何属性或邻接会引发异常(与user.setLocation(approxLocation)一起发生)。

我还试图模拟Location类并从模拟的mapsApi返回一个模拟位置。这个问题是我无法将模拟位置顶点设置为真实用户顶点的邻接 - 当我尝试执行此操作时,我们的图形数据库库(tinkerpop3)会抛出错误(同样,使用user.setLocation( approxLocation))。

不幸的是 - 改变处理交易的方式是不可能的。

有关此问题的最佳解决方案的任何想法?

1 个答案:

答案 0 :(得分:0)

更新原始updateLocation(String s)以注入Location对象