mockito_Mockito – JAXB的RETURNS_DEEP_STUBS

mockito

很抱歉没有写一段时间,但是我正忙于为DZone编写JBoss Drools Refcard,而且我正在写一本有关Mockito的书,因此我没有太多时间来写博客了……

无论如何,最近在我当前的项目中,我对使用Mockito和JAXB结构进行单元测试有一个有趣的情况。 我们已经从为我们提供的模式生成的嵌套了非常深的JAXB结构,这意味着我们无论如何都无法更改它。

让我们看一下项目结构:

project_structure

项目结构非常简单–有一个Player.xsd模式文件,该文件由于使用了jaxb2-maven-plugin生成了与目标/ jaxb /文件夹中定义的相应包中的模式相对应的生成的JAXB Java类。 pom.xml 。 说到其中,让我们看一下pom.xml文件。

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.blogspot.toomuchcoding</groupId>
 <artifactId>mockito-deep_stubs</artifactId>
 <version>0.0.1-SNAPSHOT</version>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>1.6</maven.compiler.source>
  <maven.compiler.target>1.6</maven.compiler.target>
 </properties>
 <repositories>
  <repository>
   <id>spring-release</id>
   <url>http://maven.springframework.org/release</url>
  </repository>
  <repository>
   <id>maven-us-nuxeo</id>
   <url>https://maven-us.nuxeo.org/nexus/content/groups/public</url>
  </repository>
 </repositories>

 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.10</version>
  </dependency>
  <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.9.5</version>
            <scope>test</scope>
        </dependency>
 </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.5.1</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <version>1.5</version>
                <executions>
                    <execution>
                        <id>xjc</id>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <packageName>com.blogspot.toomuchcoding.model</packageName>
                    <schemaDirectory>${project.basedir}/src/main/resources/xsd</schemaDirectory>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

除了先前定义的项目依赖关系外,如先前在配置节点的jaxb2-maven-plugin中所述,您还可以基于schemaDirectory值定义packageName值,该值定义应将JAXB类生成到哪个包,插件可以在其中找到适当的架构文件。

说到哪个,我们来检查Player.xsd模式文件( 类似于我Spring JMS自动消息转换文章中提供的文件 ):

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:element name="PlayerDetails">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="Name" type="xsd:string"/>
                <xsd:element name="Surname" type="xsd:string"/>
                <xsd:element name="Position" type="PositionType"/>
                <xsd:element name="Age" type="xsd:int"/>
                <xsd:element name="ClubDetails" type="ClubDetails"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

    <xsd:complexType name="ClubDetails">
        <xsd:sequence>
            <xsd:element name="TeamName" type="xsd:string"/>
            <xsd:element name="Country" type="CountryDetails"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="CountryDetails">
        <xsd:sequence>
            <xsd:element name="CountryName" type="xsd:string"/>
            <xsd:element name="CountryCode" type="CountryCodeDetails"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="CountryCodeDetails">
        <xsd:sequence>
            <xsd:element name="CountryName" type="xsd:string"/>
            <xsd:element name="CountryCode" type="CountryCodeType"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:simpleType name="CountryCodeType">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="PL"/>
            <xsd:enumeration value="GER"/>
            <xsd:enumeration value="FRA"/>
            <xsd:enumeration value="ENG"/>
            <xsd:enumeration value="ESP"/>
        </xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="PositionType">
        <xsd:restriction base="xsd:string">
            <xsd:enumeration value="GK"/>
            <xsd:enumeration value="DEF"/>
            <xsd:enumeration value="MID"/>
            <xsd:enumeration value="ATT"/>
        </xsd:restriction>
    </xsd:simpleType>

</xsd:schema>

如您所见,我正在定义一些复杂的类型,尽管这些类型可能没有商业意义,但您可以在现实生活中找到此类示例。

让我们找出我们要测试的方法的外观。 在这里,我们有PlayerServiceImpl实现了PlayerService接口:

package com.blogspot.toomuchcoding.service;

import com.blogspot.toomuchcoding.model.PlayerDetails;

/**
 * User: mgrzejszczak
 * Date: 08.06.13
 * Time: 19:02
 */
public class PlayerServiceImpl implements PlayerService {
    @Override
    public boolean isPlayerOfGivenCountry(PlayerDetails playerDetails, String country) {
        String countryValue = playerDetails.getClubDetails().getCountry().getCountryCode().getCountryCode().value();
        return countryValue.equalsIgnoreCase(country);
    }
}

我们从JAXB生成的类中获取嵌套元素。 尽管它违反了Demeter定律,但调用结构的方法却很常见,因为JAXB生成的类实际上是结构,因此,我完全同意Martin Fowler的观点,即应将其称为Demeter的建议 。 无论如何,让我们看看如何测试该方法:

@Test
    public void shouldReturnTrueIfCountryCodeIsTheSame() throws Exception {
        //given
        PlayerDetails playerDetails = new PlayerDetails();
        ClubDetails clubDetails = new ClubDetails();
        CountryDetails countryDetails = new CountryDetails();
        CountryCodeDetails countryCodeDetails = new CountryCodeDetails();
        playerDetails.setClubDetails(clubDetails);
        clubDetails.setCountry(countryDetails);
        countryDetails.setCountryCode(countryCodeDetails);
        countryCodeDetails.setCountryCode(CountryCodeType.ENG);

        //when
        boolean playerOfGivenCountry = objectUnderTest.isPlayerOfGivenCountry(playerDetails, COUNTRY_CODE_ENG);

        //then
        assertThat(playerOfGivenCountry, is(true));
    }

该函数检查是否具有相同的国家(地区)代码,是否从方法中获取了一个真正的布尔值。 唯一的问题是要创建输入消息时发生的集合和实例化的数量。 在我们的项目中,嵌套元素的数量是原来的两倍,因此您只能想象创建输入对象所需的代码数量…

那么如何改善此代码呢? Mockito与Mockito.mock(…)方法的RETURN_DEEP_STUBS默认答案一起出手

@Test
    public void shouldReturnTrueIfCountryCodeIsTheSameUsingMockitoReturnDeepStubs() throws Exception {
        //given
        PlayerDetails playerDetailsMock = mock(PlayerDetails.class, RETURNS_DEEP_STUBS);
        CountryCodeType countryCodeType = CountryCodeType.ENG;
        when(playerDetailsMock.getClubDetails().getCountry().getCountryCode().getCountryCode()).thenReturn(countryCodeType);

        //when
        boolean playerOfGivenCountry = objectUnderTest.isPlayerOfGivenCountry(playerDetailsMock, COUNTRY_CODE_ENG);

        //then
        assertThat(playerOfGivenCountry, is(true));
    }

因此,这里发生的是您使用Mockito.mock(…)方法并提供了RETURNS_DEEP_STUBS答案,该答案将为您自动创建模拟 。 请注意,不能嘲笑枚举,这就是为什么您不能在Mockito.when(…)函数playerDetailsMock.getClubDetails()。getCountry()。getCountryCode()。getCountryCode()。getValue()中编写代码的原因。

总结一下,您可以比较两个测试的可读性,并通过使用Mockito RETURNS_DEEP_STUBS默认答案来了解使用JAXB结构有多清晰。

当然,该示例的资源可从BitBucketGitHub获得

参考: Mockito – JAXB的RETURNS_DEEP_STUBS,来自我们的JCG合作伙伴 Marcin Grzejszczak,位于Blog上,用于编码上瘾者博客。

翻译自: https://www.javacodegeeks.com/2013/07/mockito-returns_deep_stubs-for-jaxb.html

mockito

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值