mockito
很抱歉没有写一段时间,但是我正忙于为DZone编写JBoss Drools Refcard,而且我正在写一本有关Mockito的书,因此我没有太多时间来写博客了……
无论如何,最近在我当前的项目中,我对使用Mockito和JAXB结构进行单元测试有一个有趣的情况。 我们已经从为我们提供的模式生成的嵌套了非常深的JAXB结构,这意味着我们无论如何都无法更改它。
项目结构非常简单–有一个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结构有多清晰。
当然,该示例的资源可从BitBucket和GitHub获得 。
翻译自: https://www.javacodegeeks.com/2013/07/mockito-returns_deep_stubs-for-jaxb.html
mockito