使用NoSQLUnit测试Spring Data Neo4j应用程序

Spring Data Neo4jSpring Data项目中的项目,它提供了Spring编程模型的扩展,用于编写使用Neo4j作为图形数据库的应用程序。 要使用NoSQLUnitSpring Data Neo4j应用程序编写测试,除了考虑Spring Data Neo4j在图形节点和关系中使用一种称为type的特殊属性(用于存储该实体的完全合格的类名)之外,您不需要做任何其他事情。

除了节点/关系级别的type属性,我们还需要为节点创建一个索引,为关系创建一个索引。 对于节点, types索引名称是必需的,而rel_types则需要rel_types 。 在这两种情况下,我们都必须将键值设置为className并将值设置为完全合格的类名。

类型映射

IndexingNodeTypeRepresentationStrategyIndexingRelationshipTypeRepresentationStrategy用作默认类型映射实现,但您也可以使用SubReferenceNodeTypeRepresentationStrategy ,该实体将实体类型存储在表示类型和接口层次结构的图中的树中,或者您可以通过实现NodeTypeRepresentationStrategy接口进行更多自定义。

动手工作

应用

Starfleet已要求我们开发一个应用程序,用于存储所有starfleet成员及其与其他starfleet成员的关系以及他们所服务的船舶。 实现此要求的最佳方法是使用Neo4j数据库作为后端系统。 此外, Spring Data Neo4j用于持久层。 该应用程序被建模为两个Java类,一个用于成员,另一个用于星际飞船。 请注意,对于此示例,关系中没有属性,因此仅对节点进行建模。

会员等级
@NodeEntity
public class Member {

        private static final String COMMANDS = "COMMANDS";

        @GraphId Long nodeId;

        private String name;

        private Starship assignedStarship;

        public Member() {
                super();
        }

        public Member(String name) {
                this.name = name;
        }

        @Fetch @RelatedTo(type=COMMANDS, direction=Direction.OUTGOING)
        private Set<Member> commands;

        public void command(Member member) {
                this.commands.add(member);
        }

        public Set<Member> commands() {
                return this.commands;
        }

        public Starship getAssignedStarship() {
                return assignedStarship;
        }

        public String getName() {
                return name;
        }

        public void assignedIn(Starship starship) {
                this.assignedStarship = starship;
        }

        //Equals and Hash methods
}
星际飞船类
@NodeEntity
public class Starship {

        private static final String ASSIGNED = "assignedStarship";

        @GraphId Long nodeId;

        private String starship;

        public Starship() {
                super();
        }

        public Starship(String starship) {
                this.starship = starship;
        }

        @RelatedTo(type = ASSIGNED, direction=Direction.INCOMING)
        private Set<Member> crew;

        public String getStarship() {
                return starship;
        }

        public void setStarship(String starship) {
                this.starship = starship;
        }

        //Equals and Hash methods
}

除了模型类之外,我们还需要两个存储库来实现CRUD操作和spring上下文 xml文件。 Spring Data Neo4j使用Spring Data Commons基础结构,使我们能够创建基于接口的存储库组合,为某些操作提供默认实现。

MemberRepository类
public interface MemberRepository extends GraphRepository<Member>,
                RelationshipOperationsRepository<Member> {

        Member findByName(String name);

}

看到除了GrapRepository接口提供的操作(如savefindAllfindById ,我们还定义了一种查询方法,也称为findByNameSpring Data Neo4j存储库(以及大多数Spring Data项目)提供了一种机制,该机制使用已知的Ruby on Rails方法定义查找程序查询来定义查询。

StarshipRepository类
public interface StarshipRepository extends GraphRepository<Starship>,
                RelationshipOperationsRepository<Starship> {
}
应用程序上下文文件
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.1.xsd
           http://www.springframework.org/schema/data/neo4j
           http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd">

     <context:component-scan base-package="com.lordofthejars.nosqlunit.springdata.neo4j"/>
     <context:annotation-config/>

     <neo4j:repositories base-package="com.lordofthejars.nosqlunit.springdata.repository"/>

</beans>

测试中

单元测试

如前所述,为Spring Data Neo4j编写数据集,除了正确地创建节点和关系属性以及定义所需的索引外,我们无需执行任何其他操作。 让我们看看通过播种来测试findByName方法的数据集
Neo4j数据库。

star-trek-TNG-dataset.xml文件
<?xml version="1.0" ?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
     <key id="name" for="node" attr.name="name" attr.type="string"></key>
     <key id="__type__" for="node" attr.name="__type__" attr.type="string"></key>
     <key id="starship" for="node" attr.name="starship" attr.type="string"></key>
     <graph id="G" edgedefault="directed">

       <node id="3">
        <data key="__type__">com.lordofthejars.nosqlunit.springdata.neo4j.Member</data>
        <data key="name">Jean-Luc Picard</data>
        <index name="__types__" key="className">com.lordofthejars.nosqlunit.springdata.neo4j.Member</index>
      </node>

      <node id="1">
        <data key="__type__">com.lordofthejars.nosqlunit.springdata.neo4j.Member</data>
        <data key="name">William Riker</data>
        <index name="__types__" key="className">com.lordofthejars.nosqlunit.springdata.neo4j.Member</index>
      </node>

      <node id="4">
        <data key="__type__">com.lordofthejars.nosqlunit.springdata.neo4j.Starship</data>
        <data key="starship">NCC-1701-E</data>
        <index name="__types__" key="className">com.lordofthejars.nosqlunit.springdata.neo4j.Starship</index>
      </node>

      <edge id="11" source="3" target="4" label="assignedStarship"></edge>
      <edge id="12" source="1" target="4" label="assignedStarship"></edge>
      <edge id="13" source="3" target="1" label="COMMANDS"></edge>

    </graph>
</graphml>

看到每个节点至少具有一个具有完全限定类名的type属性,以及一个具有名称types ,键className和完全限定类名作为值的索引。 下一步是配置单元测试的应用程序上下文。 application-context-embedded-neo4j.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.1.xsd
           http://www.springframework.org/schema/data/neo4j
           http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd">


        <import resource="classpath:com/lordofthejars/nosqlunit/springdata/neo4j/application-context.xml"/>
        <neo4j:config storeDirectory="target/config-test"/>

</beans>

注意,我们使用Neo4j名称空间来实例化嵌入式Neo4j数据库。 现在我们可以编写JUnit测试用例: WhenInformationAboutAMemberIsRequired

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("application-context-embedded-neo4j.xml")
public class WhenInformationAboutAMemberIsRequired {

        @Autowired
        private MemberRepository memberRepository;
        @Autowired
        private StarshipRepository starshipRepository;

        @Autowired
        private ApplicationContext applicationContext;

        @Rule
        public Neo4jRule neo4jRule = newNeo4jRule()
                        .defaultSpringGraphDatabaseServiceNeo4j();

        @Test
        @UsingDataSet(locations = "star-trek-TNG-dataset.xml", loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
        public void information_about_starship_where_serves_and_members_under_his_service_should_be_retrieved()  {

                Member jeanLuc = memberRepository.findByName("Jean-Luc Picard");

                assertThat(jeanLuc, is(createMember("Jean-Luc Picard")));
                assertThat(jeanLuc.commands(), containsInAnyOrder(createMember("William Riker")));


                Starship starship = starshipRepository.findOne(jeanLuc.getAssignedStarship().nodeId);
                assertThat(starship, is(createStarship("NCC-1701-E")));
        }

        private Object createStarship(String starship) {
                return new Starship(starship);
        }

        private static Member createMember(String memberName) {
                return new Member(memberName);
        }
}

在上一课中有一些要考虑的重点:

  1. 回想一下,我们需要使用Spring ApplicationContext对象来检索定义到Spring应用程序上下文中的嵌入式Neo4j实例。
  2. 由于数据库的生命周期由Spring Data容器管理,因此无需定义任何NoSQLUnit生命周期管理器。
整合测试

单元测试通常针对嵌入式内存实例运行,但是在生产环境中,您可能需要使用Rest连接来访问外部Neo4j服务器,或者在Spring Data Neo4j实例化SpringRestGraphDatabase类的情况下。 当您将代码与远程服务器集成时,需要编写测试以验证您的应用程序仍然可以正常工作,并且该测试通常称为集成测试。 为我们的应用程序编写集成测试就像使用SpringRestGraphDatabase定义应用程序上下文一样容易,并允许NoSQLUnit控制Neo4j数据库的生命周期。

.application-context-managed-neo4j.xml
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.1.xsd
           http://www.springframework.org/schema/data/neo4j
           http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd">


        <import resource="classpath:com/lordofthejars/nosqlunit/springdata/neo4j/application-context.xml"/>

        <bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
                <constructor-arg index="0" value="http://localhost:7474/db/data"></constructor-arg>
        </bean>
        <neo4j:config graphDatabaseService="graphDatabaseService"/>

</beans>

请注意,我们不是配置嵌入式实例,而是配置SpringRestGraphDatabase类以连接到本地主机服务器。 让我们实施一个集成测试,以验证所有星际飞船都可以从Neo4j服务器中检索到。

何时需要有关会员的信息
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("application-context-managed-neo4j.xml")
public class WhenInformationAboutStarshipsAreRequired {

        @ClassRule
        public static ManagedNeoServer managedNeoServer = newManagedNeo4jServerRule()
                        .neo4jPath(
                                        "/Users/alexsotobueno/Applications/neo4j-community-1.7.2")
                        .build();

        @Autowired
        private StarshipRepository starshipRepository;

        @Autowired
        private ApplicationContext applicationContext;

        @Rule
        public Neo4jRule neo4jRule = newNeo4jRule()
                        .defaultSpringGraphDatabaseServiceNeo4j();

        @Test
        @UsingDataSet(locations = "star-trek-TNG-dataset.xml", loadStrategy = LoadStrategyEnum.CLEAN_INSERT)
        public void information_about_starship_where_serves_and_members_under_his_service_should_be_retrieved() {

                EndResult<Starship> allStarship = starshipRepository.findAll();

                assertThat(allStarship, containsInAnyOrder(createStarship("NCC-1701-E")));

        }

        private Object createStarship(String starship) {
                return new Starship(starship);
        }

}

由于defaultSpringGraphDatabaseServiceNeo4j方法将定义的GraphDatabaseService实例返回到应用程序上下文中 ,因此在我们的示例中,它将返回定义的SpringRestGraphDatabase实例。

结论

为无Spring Data Neo4j应用程序编写测试与为它们使用应用程序编写测试之间没有太大区别。 仅记住正确定义type属性并创建所需的索引。 从NoSQLUnit的角度来看,除了数据库引擎的生命周期管理之外,编写单元测试或集成测试也没有区别。 下载代码

参考:来自JCG合作伙伴 Alex Soto的NoSQLUnit使用NoSQLUnit测试Spring Data Neo4j应用程序,来自One Jar To Rule All All博客。

翻译自: https://www.javacodegeeks.com/2013/03/testing-spring-data-neo4j-applications-with-nosqlunit.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值