mirror of
https://github.com/OpenBankProject/OBP-API.git
synced 2026-02-06 13:26:51 +00:00
refactor, add missing unit test
This commit is contained in:
parent
f3f155d507
commit
22aebe1426
@ -124,8 +124,6 @@
|
||||
<dependency>
|
||||
<groupId>org.scalatest</groupId>
|
||||
<artifactId>scalatest_${scala.version}</artifactId>
|
||||
<version>3.0.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.eclipse.jetty/jetty-server -->
|
||||
<dependency>
|
||||
|
||||
@ -9429,37 +9429,28 @@ trait RestConnector_vMar2019 extends Connector with KafkaHelper with MdcLoggable
|
||||
*/
|
||||
private def convertId[T](obj: T, customerIdConverter: String=> String, accountIdConverter: String=> String): T = {
|
||||
//1st: We must not convert when connector == mapped. this will ignore the implicitly_convert_ids props.
|
||||
//2rd: if connector != mapped, we still need the `implicitly_convert_ids == true`
|
||||
if(APIUtil.getPropsValue("connector","mapped") != "mapped" && APIUtil.getPropsAsBoolValue("implicitly_convert_ids",false)){
|
||||
ReflectUtils.operateNestedValues(obj)(fieldMirror => {
|
||||
val fieldValue = fieldMirror.get
|
||||
val fieldSymbol: TermSymbol = fieldMirror.symbol
|
||||
val fieldType: Type = fieldSymbol.info
|
||||
val fieldName: String = fieldSymbol.name.toString.trim.toLowerCase
|
||||
|
||||
val ownerSymbol: Type = fieldSymbol.owner.asType.toType
|
||||
|
||||
if(fieldValue == null) {
|
||||
// do nothing
|
||||
} else if (ownerSymbol <:< typeOf[CustomerId] ||
|
||||
(fieldName == "customerid" && fieldType =:= typeOf[String]) ||
|
||||
(ownerSymbol <:< typeOf[Customer] && fieldName == "id" && fieldType =:= typeOf[String])
|
||||
) {
|
||||
val customerRef = customerIdConverter(fieldValue.asInstanceOf[String])
|
||||
fieldMirror.set(customerRef)
|
||||
} else if(ownerSymbol <:< typeOf[AccountId] ||
|
||||
(fieldName == "accountid" && fieldType =:= typeOf[String]) ||
|
||||
(ownerSymbol <:< typeOf[CoreAccount] && fieldName == "id" && fieldType =:= typeOf[String])||
|
||||
(ownerSymbol <:< typeOf[AccountBalance] && fieldName == "id" && fieldType =:= typeOf[String])||
|
||||
(ownerSymbol <:< typeOf[AccountHeld] && fieldName == "id" && fieldType =:= typeOf[String])
|
||||
) {
|
||||
val accountRef = accountIdConverter(fieldValue.asInstanceOf[String])
|
||||
fieldMirror.set(accountRef)
|
||||
}
|
||||
})
|
||||
obj
|
||||
} else
|
||||
obj
|
||||
//2rd: if connector != mapped, we still need the `implicitly_convert_ids == true`
|
||||
|
||||
def isCustomerId(fieldName: String, fieldType: Type, fieldValue: Any, ownerType: Type) = {
|
||||
ownerType =:= typeOf[CustomerId] ||
|
||||
(fieldName.equalsIgnoreCase("customerId") && fieldType =:= typeOf[String]) ||
|
||||
(ownerType <:< typeOf[Customer] && fieldName.equalsIgnoreCase("id") && fieldType =:= typeOf[String])
|
||||
}
|
||||
|
||||
def isAccountId(fieldName: String, fieldType: Type, fieldValue: Any, ownerType: Type) = {
|
||||
ownerType <:< typeOf[AccountId] ||
|
||||
(fieldName.equalsIgnoreCase("accountId") && fieldType =:= typeOf[String])
|
||||
(ownerType <:< typeOf[CoreAccount] && fieldName.equalsIgnoreCase("id") && fieldType =:= typeOf[String])||
|
||||
(ownerType <:< typeOf[AccountBalance] && fieldName.equalsIgnoreCase("id") && fieldType =:= typeOf[String])||
|
||||
(ownerType <:< typeOf[AccountHeld] && fieldName.equalsIgnoreCase("id") && fieldType =:= typeOf[String])
|
||||
}
|
||||
|
||||
ReflectUtils.resetNestedFields(obj){
|
||||
case (fieldName, fieldType, fieldValue: String, ownerType) if isCustomerId(fieldName, fieldType, fieldValue, ownerType) => customerIdConverter(fieldValue)
|
||||
case (fieldName, fieldType, fieldValue: String, ownerType) if isAccountId(fieldName, fieldType, fieldValue, ownerType) => accountIdConverter(fieldValue)
|
||||
}
|
||||
|
||||
obj
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -13,6 +13,14 @@
|
||||
<packaging>jar</packaging>
|
||||
<name>Open Bank Project Commons</name>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>artima</id>
|
||||
<name>Artima Maven Repository</name>
|
||||
<url>http://repo.artima.com/releases</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>net.liftweb</groupId>
|
||||
@ -27,13 +35,23 @@
|
||||
<dependency>
|
||||
<groupId>org.scalatest</groupId>
|
||||
<artifactId>scalatest_${scala.version}</artifactId>
|
||||
<version>3.0.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.scalactic</groupId>
|
||||
<artifactId>scalactic_${scala.version}</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${scala.version}</version>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>net.alchim31.maven</groupId>
|
||||
<artifactId>scala-maven-plugin</artifactId>
|
||||
@ -47,6 +65,13 @@
|
||||
<scalaCompatVersion>${scala.version}</scalaCompatVersion>
|
||||
<recompileMode>incremental</recompileMode>
|
||||
<useZincServer>true</useZincServer>
|
||||
<compilerPlugins>
|
||||
<compilerPlugin>
|
||||
<groupId>com.artima.supersafe</groupId>
|
||||
<artifactId>supersafe_${scala.compiler}</artifactId>
|
||||
<version>1.1.8</version>
|
||||
</compilerPlugin>
|
||||
</compilerPlugins>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
|
||||
@ -71,8 +71,6 @@ object OBPEnumeration {
|
||||
|
||||
def getValuesByClass[T <: EnumValue](clazz: Class[T]): List[T] = getEnumContainer(clazz).values
|
||||
|
||||
def getValues[T <: EnumValue: TypeTag]: List[T] = getEnumContainer(typeTag[T].tpe).values.map(_.asInstanceOf[T])
|
||||
|
||||
def withNameOption(tp: Type, name: String): Option[EnumValue] = getEnumContainer(tp).withNameOption(name).map(_.asInstanceOf[EnumValue])
|
||||
|
||||
def withNameOption[T <: EnumValue](clazz: Class[T], name: String): Option[T] = getEnumContainer(clazz).withNameOption(name)
|
||||
|
||||
@ -56,14 +56,17 @@ object ReflectUtils {
|
||||
def setField[T](obj: AnyRef, fieldName: String, fieldValue: T): T = operateField[T](obj, fieldName, _.set(fieldValue))
|
||||
|
||||
/**
|
||||
* modify given instance nested values
|
||||
* modify given instance nested fields value
|
||||
* @param obj given instance to modify
|
||||
* @param predicate check whether current field value need to modify
|
||||
* @param fn modify function
|
||||
* @param fn modify function, signature is (fieldName: String, fieldType: Type, fieldValue: Any, ownerType: Type): Any
|
||||
* fn result is calculated new value
|
||||
* @return modified instance
|
||||
*
|
||||
* @note be carefully, this method will modify immutable object state, before you call this method, you should very sure it is safe for your logic.
|
||||
*/
|
||||
def operateNestedValues(obj: Any, predicate: Any => Boolean = isObpObject)(fn: ru.FieldMirror => Unit): Any = {
|
||||
val recurseCallback = operateNestedValues(_: Any, predicate)(fn)
|
||||
def resetNestedFields(obj: Any, predicate: Any => Boolean = isObpObject)(fn: PartialFunction[(String, Type, Any, Type), Any]): Any = {
|
||||
val recurseCallback = resetNestedFields(_: Any, predicate)(fn)
|
||||
obj match {
|
||||
case null | None | Empty | Nil => obj
|
||||
case _: Unit => obj
|
||||
@ -85,7 +88,7 @@ object ReflectUtils {
|
||||
case v: Array[_] => v.map(recurseCallback)
|
||||
case v: Map[_, _] => v.values.map(recurseCallback)
|
||||
case v: Iterable[_] => v.map(recurseCallback)
|
||||
case v if(!predicate(v)) => v
|
||||
case v if !predicate(v) => v
|
||||
case _ => {
|
||||
val tp = this.getType(obj)
|
||||
val instanceMirror: ru.InstanceMirror = mirror.reflect(obj)
|
||||
@ -98,8 +101,18 @@ object ReflectUtils {
|
||||
constructFieldNames.foreach(it => {
|
||||
val fieldSymbol: ru.TermSymbol = getType(obj).member(ru.TermName(it)).asTerm.accessed.asTerm
|
||||
val fieldMirror: ru.FieldMirror = instanceMirror.reflectField(fieldSymbol)
|
||||
recurseCallback(fieldMirror.get)
|
||||
fn(fieldMirror)
|
||||
val fieldValue: Any = fieldMirror.get
|
||||
recurseCallback(fieldValue)
|
||||
|
||||
//check whether field should modify, if PartialFunction check result is true, just modify it with new Value
|
||||
val fieldName: String = it
|
||||
val fieldType: Type = fieldSymbol.info
|
||||
val ownerType: Type = fieldSymbol.owner.asType.toType
|
||||
|
||||
if(fn.isDefinedAt(fieldName, fieldType, fieldValue, ownerType)) {
|
||||
val newValue = fn(fieldName, fieldType, fieldValue, ownerType)
|
||||
fieldMirror.set(newValue)
|
||||
}
|
||||
})
|
||||
obj
|
||||
}
|
||||
|
||||
@ -0,0 +1,241 @@
|
||||
package com.openbankproject.commons.util
|
||||
|
||||
import com.openbankproject.commons.util.Color.Color
|
||||
import com.openbankproject.commons.util.Shape.Shape
|
||||
import org.scalatest._
|
||||
|
||||
import scala.reflect.runtime.universe._
|
||||
|
||||
import org.scalatest.Tag
|
||||
|
||||
// to show bad design of scala enumeration
|
||||
object Shape extends Enumeration {
|
||||
type Shape = Value
|
||||
val Circle = Value
|
||||
val Square = Value
|
||||
val Other = Value
|
||||
}
|
||||
|
||||
object Color extends Enumeration {
|
||||
type Color = Value
|
||||
val Red = Value
|
||||
val Green = Value
|
||||
val Other = Value
|
||||
}
|
||||
|
||||
object OBPEnumTag extends Tag("OBPEnumeration")
|
||||
/**
|
||||
* just for demonstrate what problem of scala enumeration, so here just set to ignore
|
||||
*/
|
||||
@Ignore
|
||||
class ScalaEnumerationTest extends FlatSpec with Matchers {
|
||||
|
||||
it should "legal to create two overloaded methods with parameter Shape and Color" taggedAs(OBPEnumTag) in {
|
||||
// if remove the comment of process method, will can't compile
|
||||
object OverloadTest{
|
||||
def process(shape: Shape) = ???
|
||||
// def process(Color: Color) = ???
|
||||
}
|
||||
}
|
||||
|
||||
it should "have compile warnings when match case is not exhaustive with enumeration" taggedAs(OBPEnumTag) in {
|
||||
val shape: Shape = Shape.Other
|
||||
shape match {
|
||||
case Shape.Other => println("hi other")
|
||||
}
|
||||
}
|
||||
|
||||
"shape.isInstanceOf[Color] " should "return false" taggedAs(OBPEnumTag) in {
|
||||
// the worst: confused type check
|
||||
val shape: Shape = Shape.Other
|
||||
|
||||
// shape is not Color, isColor should be false
|
||||
val isColor = shape.isInstanceOf[Color]
|
||||
isColor shouldBe false
|
||||
}
|
||||
"shape cast to Color" should "throw ClassCastException" taggedAs(OBPEnumTag) in {
|
||||
val shape: Shape = Shape.Other
|
||||
// shape cast to Color should throw ClassCastException
|
||||
a[ClassCastException] should be thrownBy {
|
||||
val color: Color = shape.asInstanceOf[Color]
|
||||
}
|
||||
}
|
||||
"if shape can be cast to Color, casted value" should "match Color value" taggedAs(OBPEnumTag) in {
|
||||
val shape: Shape = Shape.Other
|
||||
val color: Color = shape.asInstanceOf[Color]
|
||||
val wrong: String = color match {
|
||||
case Color.Other => "match Color#other"
|
||||
case _ => "NOT MATCH"
|
||||
}
|
||||
color.toString shouldBe "Other"
|
||||
|
||||
wrong shouldBe "match Color#other"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// to demonstrate OBPEnumeration
|
||||
sealed trait OBPShape extends EnumValue
|
||||
|
||||
object OBPShape extends OBPEnumeration[OBPShape]{
|
||||
object Circle extends OBPShape
|
||||
object Square extends OBPShape
|
||||
object Other extends OBPShape
|
||||
}
|
||||
|
||||
sealed trait OBPColor extends EnumValue
|
||||
|
||||
object OBPColor extends OBPEnumeration[OBPColor]{
|
||||
object Red extends OBPColor
|
||||
object Green extends OBPColor
|
||||
object Other extends OBPColor
|
||||
}
|
||||
|
||||
class OBPEnumerationTest extends FlatSpec with Matchers {
|
||||
it should "legal to create two overloaded methods with parameter OBPShape and OBPColor" taggedAs(OBPEnumTag) in {
|
||||
// first bad: can't overload for different enumeration
|
||||
object OverloadTest{
|
||||
def process(shape: OBPShape) = ???
|
||||
def process(Color: OBPColor) = ???
|
||||
}
|
||||
}
|
||||
|
||||
it should "have compile warnings when match case is not exhaustive with enumeration" taggedAs(OBPEnumTag) in {
|
||||
val shape: OBPShape = OBPShape.Other
|
||||
shape match {
|
||||
case OBPShape.Other => "hi other"
|
||||
}
|
||||
}
|
||||
|
||||
"shape.isInstanceOf[OBPColor] " should "return false" taggedAs(OBPEnumTag) in {
|
||||
// the worst: confused type check
|
||||
val shape: OBPShape = OBPShape.Other
|
||||
|
||||
// shape is not Color, isColor should be false
|
||||
val isColor = shape.isInstanceOf[OBPColor]
|
||||
isColor shouldBe false
|
||||
}
|
||||
|
||||
"shape cast to Color" should "throw ClassCastException" taggedAs(OBPEnumTag) in {
|
||||
val shape: OBPShape = OBPShape.Other
|
||||
// shape cast to Color should throw ClassCastException
|
||||
a [ClassCastException] should be thrownBy {
|
||||
val color = shape.asInstanceOf[OBPColor]
|
||||
}
|
||||
}
|
||||
|
||||
"values" should "contains all values" taggedAs(OBPEnumTag) in {
|
||||
OBPShape.values should contain only (OBPShape.Square, OBPShape.Circle, OBPShape.Other)
|
||||
}
|
||||
|
||||
"example" should "be one value of OBPShape enumeration" taggedAs(OBPEnumTag) in {
|
||||
OBPShape.example shouldBe a [OBPShape]
|
||||
}
|
||||
"nameToValue" should "be name map to value of OBPShape enumeration" taggedAs(OBPEnumTag) in {
|
||||
OBPShape.nameToValue should contain theSameElementsAs Map("Square" -> OBPShape.Square, "Circle" -> OBPShape.Circle, "Other" -> OBPShape.Other)
|
||||
}
|
||||
|
||||
it should "get a Some(v) value when call withNameOption to retrieve exists OBPShape value" taggedAs(OBPEnumTag) in {
|
||||
OBPShape.withNameOption("Square") shouldBe Some(OBPShape.Square)
|
||||
}
|
||||
|
||||
it should "get a None value when call withNameOption to retrieve not exists OBPShape value" taggedAs(OBPEnumTag) in {
|
||||
OBPShape.withNameOption("NOT_EXISTS") shouldBe None
|
||||
}
|
||||
|
||||
it should "get a value when call withName to retrieve exists OBPShape value" taggedAs(OBPEnumTag) in {
|
||||
OBPShape.withName("Circle") shouldBe OBPShape.Circle
|
||||
}
|
||||
|
||||
it should "throw NoSuchElementException when call withName to retrieve not exists OBPShape value" taggedAs(OBPEnumTag) in {
|
||||
a [NoSuchElementException] should be thrownBy {
|
||||
OBPShape.withName("NOT_EXISTS") shouldBe OBPShape.Circle
|
||||
}
|
||||
}
|
||||
|
||||
// the follow test is for OBPEnumeration utils functions
|
||||
"call OBPEnumeration.getValuesByType with an OBPEnumeration type" should "get all values" taggedAs(OBPEnumTag) in {
|
||||
val unknownType = typeOf[OBPColor]
|
||||
OBPEnumeration.getValuesByType(unknownType) shouldBe(OBPColor.values)
|
||||
}
|
||||
"call OBPEnumeration.getValuesByClass with an OBPEnumeration type" should "get all values" taggedAs(OBPEnumTag) in {
|
||||
val unknownClazz = classOf[OBPShape].asInstanceOf[Class[EnumValue]]
|
||||
OBPEnumeration.getValuesByClass(unknownClazz) should be(OBPShape.values)
|
||||
}
|
||||
"call OBPEnumeration.withNameOption with an OBPEnumeration type OR class and exists name" should "get correct Some(v)" taggedAs(OBPEnumTag) in {
|
||||
val unknownType = typeOf[OBPShape]
|
||||
val unknownClazz = classOf[OBPShape].asInstanceOf[Class[EnumValue]]
|
||||
|
||||
OBPEnumeration.withNameOption(unknownType, "Square") shouldBe Some(OBPShape.Square)
|
||||
OBPEnumeration.withNameOption(unknownClazz, "Circle") shouldBe Some(OBPShape.Circle)
|
||||
}
|
||||
"call OBPEnumeration.withNameOption with an OBPEnumeration type OR class and not exists name" should "get correct None" taggedAs(OBPEnumTag) in {
|
||||
val unknownType = typeOf[OBPShape]
|
||||
val unknownClazz = classOf[OBPShape].asInstanceOf[Class[EnumValue]]
|
||||
|
||||
OBPEnumeration.withNameOption(unknownType, "NOT_EXISTS") shouldBe empty
|
||||
OBPEnumeration.withNameOption(unknownClazz, "NOT_EXISTS") shouldBe empty
|
||||
}
|
||||
"call OBPEnumeration.withName with an OBPEnumeration type OR class and exists name" should "get correct value" taggedAs(OBPEnumTag) in {
|
||||
val unknownType = typeOf[OBPShape]
|
||||
val unknownClazz = classOf[OBPShape].asInstanceOf[Class[EnumValue]]
|
||||
|
||||
OBPEnumeration.withName(unknownType, "Square") shouldBe OBPShape.Square
|
||||
OBPEnumeration.withName(unknownClazz, "Circle") shouldBe OBPShape.Circle
|
||||
}
|
||||
"call OBPEnumeration.withName with an OBPEnumeration type OR class and not exists name" should "throw NoSuchElementException" taggedAs(OBPEnumTag) in {
|
||||
a [NoSuchElementException] should be thrownBy {
|
||||
val unknownType = typeOf[OBPShape]
|
||||
OBPEnumeration.withName(unknownType, "NOT_EXISTS")
|
||||
}
|
||||
|
||||
a [NoSuchElementException] should be thrownBy {
|
||||
val unknownClazz = classOf[OBPShape].asInstanceOf[Class[EnumValue]]
|
||||
OBPEnumeration.withName(unknownClazz, "NOT_EXISTS")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
"call OBPEnumeration.withIndexOption with an OBPEnumeration type OR class and exists taggedAs(OBPEnumTag) index" should "get correct Some(v)" taggedAs(OBPEnumTag) in {
|
||||
val unknownType = typeOf[OBPShape]
|
||||
val unknownClazz = classOf[OBPShape].asInstanceOf[Class[EnumValue]]
|
||||
|
||||
OBPEnumeration.withIndexOption(unknownType, 0) shouldBe Some(OBPShape.Circle)
|
||||
OBPEnumeration.withIndexOption(unknownClazz, 1) shouldBe Some(OBPShape.Square)
|
||||
}
|
||||
"call OBPEnumeration.withIndexOption with an OBPEnumeration type OR class and not exists taggedAs(OBPEnumTag) index" should "get correct None" taggedAs(OBPEnumTag) in {
|
||||
val unknownType = typeOf[OBPShape]
|
||||
val unknownClazz = classOf[OBPShape].asInstanceOf[Class[EnumValue]]
|
||||
|
||||
OBPEnumeration.withIndexOption(unknownType, 4) shouldBe empty
|
||||
OBPEnumeration.withIndexOption(unknownClazz, -1) shouldBe empty
|
||||
}
|
||||
"call OBPEnumeration.withIndex with an OBPEnumeration type OR class and exists taggedAs(OBPEnumTag) index" should "get correct value" taggedAs(OBPEnumTag) in {
|
||||
val unknownType = typeOf[OBPShape]
|
||||
val unknownClazz = classOf[OBPShape].asInstanceOf[Class[EnumValue]]
|
||||
|
||||
OBPEnumeration.withIndex(unknownType, 0) shouldBe OBPShape.Circle
|
||||
OBPEnumeration.withIndex(unknownClazz, 1) shouldBe OBPShape.Square
|
||||
}
|
||||
"call OBPEnumeration.withIndex with an OBPEnumeration type OR class and not exists taggedAs(OBPEnumTag) index" should "throw NoSuchElementException" taggedAs(OBPEnumTag) in {
|
||||
a [NoSuchElementException] should be thrownBy {
|
||||
val unknownType = typeOf[OBPShape]
|
||||
OBPEnumeration.withIndex(unknownType, 8)
|
||||
}
|
||||
|
||||
a [NoSuchElementException] should be thrownBy {
|
||||
val unknownClazz = classOf[OBPShape].asInstanceOf[Class[EnumValue]]
|
||||
OBPEnumeration.withIndex(unknownClazz, -1)
|
||||
}
|
||||
}
|
||||
|
||||
"call OBPEnumeration.getExampleByType" should "get one of values" taggedAs(OBPEnumTag) in {
|
||||
val unknownType = typeOf[OBPShape]
|
||||
OBPEnumeration.getExampleByType(unknownType) shouldBe(OBPShape.Circle)
|
||||
}
|
||||
|
||||
"call OBPEnumeration.getExampleByClass" should "get one of values" taggedAs(OBPEnumTag) in {
|
||||
val unknownClazz = classOf[OBPColor].asInstanceOf[Class[EnumValue]]
|
||||
OBPEnumeration.getExampleByClass(unknownClazz) shouldBe(OBPColor.Red)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
package com.openbankproject.commons.util
|
||||
|
||||
import org.scalatest.{FlatSpec, Matchers}
|
||||
import scala.reflect.runtime.universe._
|
||||
import org.scalatest.Tag
|
||||
|
||||
class ReflectUtilsTest extends FlatSpec with Matchers {
|
||||
object ReflectUtilsTag extends Tag("ReflectUtils")
|
||||
|
||||
case class Aperson(id: String, age: Int)
|
||||
case class Agroup(manager: Aperson, id: Int, members: List[Aperson])
|
||||
|
||||
|
||||
"when modify Apersion#id to append suffix" should "all the not null id be end with suffix" taggedAs(ReflectUtilsTag) in {
|
||||
val members = List(Aperson(null, 10), Aperson("p1-id", 20), Aperson("p2-id", 3))
|
||||
val group = Agroup(Aperson("m-id", 11), 3, members)
|
||||
val someGroup = Some(group)
|
||||
|
||||
val idSuffix = "---END"
|
||||
|
||||
ReflectUtils.resetNestedFields(someGroup){
|
||||
case (fieldName, fieldType, fieldValue: String, ownerType) if(fieldName == "id" && ownerType =:= typeOf[Aperson]) =>
|
||||
fieldValue + idSuffix
|
||||
}
|
||||
|
||||
group.manager.id should endWith (idSuffix)
|
||||
group.id shouldBe(3)
|
||||
group.members.head.id shouldBe null
|
||||
group.members.lift(1).get.id should endWith (idSuffix)
|
||||
group.members.lift(2).get.id should endWith (idSuffix)
|
||||
}
|
||||
}
|
||||
12
pom.xml
12
pom.xml
@ -81,6 +81,18 @@
|
||||
<artifactId>lift-common_${scala.version}</artifactId>
|
||||
<version>${lift.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.scalatest</groupId>
|
||||
<artifactId>scalatest_${scala.version}</artifactId>
|
||||
<version>3.0.8</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.scalactic</groupId>
|
||||
<artifactId>scalactic_${scala.version}</artifactId>
|
||||
<version>3.0.8</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user