使用 neo4j-spatial 密码查询与 SDN4 存储库进行集成测试

Integration testing with SDN4 repositories using neo4j-spatial cypher queries

我开始在我的一些代码中使用 neo4j-spatial。我认为我可以通过将空间服务器库作为 Maven 依赖项包含在我的项目中来集成测试 neo4j-spatial 代码。但这对我不起作用。我在任何地方都找不到任何文档。

如何让我的集成测试工作?

有人有什么建议吗? :)

为了让大家了解我在做什么,我在下面粘贴了我的控制器、服务和存储库代码的一部分,最后发布的代码是我的测试,它不适用于嵌入式 TestServer .

存储库

package nz.co.domain.core.repository.location;

import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import nz.co.domain.model.pojos.Location;

@Repository
public interface LocationRepository extends GraphRepository<Location> {

    @Query("match (n:Location {domainId : {domainId}}) with n call spatial.addNode({layerName}, n) yield node return node;")
    public Location indexLocation(@Param("domainId") String locationId, @Param("layerName") String layerName);

    @Query("call spatial.withinDistance({layerName},{longitude: {longitude},latitude: {latitude}}, {rangeInKms});")
    public Iterable<Location> findLocationsWithinRange(@Param("longitude") String longitude, @Param("latitude") String latitude, @Param("rangeInKms") String rangeInKms, @Param("layerName") String layerName);

    @Query("call spatial.addPointLayer({layerName});")
    public void createLayer(@Param("layerName") String layerName);

    @Query("match ()-[:LAYER]->(n) where n.layer = {layerName} return count(n) > 0;")
    public boolean hasLayer(@Param("layerName") String layerName);

    public Location findByDomainSpecificId(String domainSpecificId);

    public Location findByGooglePlaceId(String googlePlaceId);

}

服务

package nz.co.domain.core.location;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import nz.co.domain.core.repository.location.LocationRepository;
import nz.co.domain.model.UniqueIDGenerator;
import nz.co.domain.model.pojos.Location;

@Service
public class LocationService {

    @Inject
    private LocationRepository locationRepository;

    public void createLayer(String layerName) { 
        locationRepository.createLayer(layerName);
    }

    public Location createLocation(double latitude, double longitude, String googlePlaceId, String layerName) { 
        Location location = new Location(UniqueIDGenerator.randomID(), googlePlaceId, latitude, longitude);
        boolean hasLayer = locationRepository.hasLayer(layerName);
        if (!hasLayer) { 
            locationRepository.createLayer(layerName);
        }

        Location preExistingLocation = locationRepository.findByGooglePlaceId(googlePlaceId);

        if (preExistingLocation == null) { 
            location = locationRepository.save(location);
            location = locationRepository.indexLocation(location.getDomainId(), layerName);
        } else { 
            location = preExistingLocation;
        }

        return location;
    }

    public Iterable<Location> findLocationsWithinRange(String latitude, String longitude, String rangeInKms, String layerName) { 
        return locationRepository.findLocationsWithinRange(longitude, latitude, rangeInKms, layerName);
    }

    public Location loadLocationByGooglePlaceId(String googlePlaceId) {
        return locationRepository.findByGooglePlaceId(googlePlaceId);
    }

    public Location loadLocationByDomainId(String domainId) {
        return locationRepository.findByDomainId(domainId);
    }

}

控制器

...

/**
     * Add location. 
     * @param profiletypes
     * @param profileId
     * @return
     */
    @RequestMapping(value = "/{profileType}/{profileId}/location", method = RequestMethod.POST, produces = "application/hal+json")
    public HttpEntity<LocationResource> addLocation(@PathVariable String profileType,
            @PathVariable String profileId, @RequestBody CreateLocationRequest locationRequest, @ApiIgnore LocationResourceAssembler locationResourceAssembler) {

        Profile profile = profileService.loadProfileByDomainId(profileId);

        Location location = locationService.createLocation(locationRequest.getLatitude(), locationRequest.getLongitude(), locationRequest.getGooglePlaceId(), profileType + "-layer");

        profile.setLocation(location);
        profileService.save(profile);

        location = locationService.loadLocationByGooglePlaceId(location.getGooglePlaceId());

        LocationResource resource = locationResourceAssembler.toResource(location);
        return new ResponseEntity<>(resource, HttpStatus.CREATED) ;
    }

...

服务测试

(我在这里的测试无法作为针对嵌入式 TestServer 的标准构建的一部分工作)

package nz.co.domain.core.location;

import javax.inject.Inject;

import org.junit.Ignore;
import org.junit.Test;

import nz.co.domain.core.AbstractTest;
import nz.co.domain.model.pojos.Location;

public class LocationServiceTest extends AbstractTest {

    @Inject
    private LocationService locationService;

    @Test
    public void indexLocationTest() { 

        // The Rogue and Vagabond
        Location rogueAndVagabond = locationService.createLocation(51.469150, 7.23212, "ChIJmwfKGdivOG0R9eTCVFOngnU", "test-layer");

        /* more test code here */

        // Te Papa Museum
        Location tePapaMuseum = locationService.createLocation(-41.289964, 174.778354, "ChIJfxn9AdGvOG0RpLRGGO3tRX8", "test-layer");

        /* more test code here */

        // Porirua Club
        Location poriruaClub = locationService.createLocation(-41.136048, 174.836409, "ChIJ9wl16m1TP20R3G3npuEokak", "test-layer");

        /* more test code here */

        Iterable<Location> findLocationsWithinRange = locationService.findLocationsWithinRange("-41.289964", "longitude", "5", "test-layer");

       /* more test code here */

    }
}

SDN 4 中还没有提供空间功能。如果您集成了 neo4j-spatial 库,那么您目前唯一的选择就是直接使用它——将没有存储库支持等。 但是,空间集成工作目前正在进行中,因此应该在下一个版本中引入一些基本功能。

我们正在使用 SDN 4.1.2、OGM 2.0.3,我的测试使用此设置:

使用 the description on the github page 添加了 maven 依赖项。在撰写此评论时,pom.xml 的必要添加是

<repositories>
    <repository>
        <id>neo4j-contrib-releases</id>
        <url>https://raw.github.com/neo4j-contrib/m2/master/releases</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
    <repository>
        <id>neo4j-contrib-snapshots</id>
        <url>https://raw.github.com/neo4j-contrib/m2/master/snapshots</url>
        <releases>
            <enabled>false</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>
<!-- ... -->
<dependency>
    <groupId>org.neo4j</groupId>
    <artifactId>neo4j-spatial</artifactId>
    <version>0.19-neo4j-3.0.3</version>
</dependency>

为所有与空间相关的测试定义以下摘要类:

@RunWith(SpringJUnit4ClassRunner::class)
@SpringApplicationConfiguration(classes = arrayOf(Application::class))
@ActiveProfiles("test")
@Transactional
abstract class AbstractIntegrationTests() {}

@WebAppConfiguration
abstract class AbstractIntegrationTestsWithProcedures : AbstractIntegrationTests() {

    lateinit var databaseService: GraphDatabaseService
    val layerName = "layer"

    @Before()
    open fun before() {
        if (ProcedureTestUtil.registeredProcedures.contains(SpatialProcedures::class.java)) {
            return
        }
        val driver = Components.driver()
        if (driver is EmbeddedDriver) {
            databaseService = driver.graphDatabaseService
            ProcedureTestUtil.registerProcedure(databaseService, SpatialProcedures::class.java)
            val spatialPlugin = SpatialPlugin()
            spatialPlugin.addSimplePointLayer(databaseService, layerName, "latitude", "longitude")
        } else {
            throw UnsupportedOperationException("Expected an embedded Neo4j instance, but was " + driver.javaClass.name)
        }
    }
}

另外

class ProcedureTestUtil {

    companion object {
        @JvmStatic
        var registeredProcedures: MutableList<Class<*>> = ArrayList()

        @JvmStatic
        @Throws(KernelException::class)
        fun registerProcedure(db: GraphDatabaseService, procedure: Class<*>) {
            val proceduresService = (db as GraphDatabaseAPI).dependencyResolver.resolveDependency(Procedures::class.java)
            proceduresService.register(procedure)
            registeredProcedures.add(procedure)
        }
    }
}

你应该接受测试 运行 如果 LocationServiceTest extends AbstractIntegrationTestsWithProcedures.