Я наблюдаю разное поведение в двух похожих тестах Grails 3.3.5. Разница между этими двумя случаями:
- В первом тестовом примере спецификация создает тестовый объект, передает его контроллеру, который добавляет / помещает его в свои две коллекции
objects1
и objects2
. Когда объект изменяется в спецификации, изменения применяются как к objects1
, так и к objects2
.
- Во втором тестовом примере контроллер сам создает объект и помещает его в свои две коллекции. Когда я прошу контроллер доставить объект из первой коллекции (
objects1
), а затем изменить этот объект в спецификации, изменения применяются только к objects1
, но не к другой коллекции objects2
.
Мой вопрос: согласно объектно-ориентированной парадигме Java и Groovy, я бы ожидал, что оба теста будут вести себя как первый тест. Почему существует разница в зависимости от того, какой класс создает объект?
Для пояснения, мой пример кода приведен здесь. Класс домена:
class MyTestObject {
String value
static constraints = {
}
MyTestObject(){
value = "initialized"
}
void edit(){
value = "edited"
}
String getValue(){
value
}
}
Контроллер класса:
class MyTestController {
def index() { }
Map<Integer, MyTestObject> objects1
Map<Integer, MyTestObject> objects2
MyTestController(){
objects1 = new HashMap<>()
objects2 = new HashMap<>()
}
void addObject(){
int count = objects1.size()
objects1.put(count, new MyTestObject())
objects2.put(count, new MyTestObject())
}
void addObject(MyTestObject testObject){
int count = objects1.size()
objects1.put(count, testObject)
objects2.put(count, testObject)
}
MyTestObject getObjectFromCollection1(int atPosition){
if (0 > atPosition || atPosition > objects1.size()-1){
return
}
objects1.get(atPosition)
}
MyTestObject getObjectFromCollection2(int atPosition){
if (0 > atPosition || atPosition > objects2.size()-1){
return
}
objects2.get(atPosition)
}
void updateObjectInCollection1(int index, MyTestObject object){
objects1.put(index, object)
}
}
Спецификация:
import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification
class MyTestControllerSpec extends Specification implements ControllerUnitTest<MyTestController> {
int index
def setup(){
index = 0
}
void "case 1: external object instantiation"() {
MyTestController controllerLocal = new MyTestController()
MyTestObject object = new MyTestObject()
controllerLocal.addObject(object)
object.edit()
MyTestObject afterEditInCollection1 = controllerLocal.getObjectFromCollection1(index)
MyTestObject afterEditInCollection2 = controllerLocal.getObjectFromCollection2(index)
expect:
"edited" == object.getValue()
"edited" == afterEditInCollection1.getValue()
"edited" == afterEditInCollection2.getValue()
}
void "case 2: internal object instantiation"() {
MyTestController controllerLocal = new MyTestController()
controllerLocal.addObject()
MyTestObject toBeEditedLocally = controllerLocal.getObjectFromCollection1(index)
toBeEditedLocally.edit()
MyTestObject afterEditInCollection1 = controllerLocal.getObjectFromCollection1(index)
MyTestObject afterEditInCollection2 = controllerLocal.getObjectFromCollection2(index)
expect:
"edited" == toBeEditedLocally.getValue()
"edited" == afterEditInCollection1.getValue()
"edited" == afterEditInCollection2.getValue()
}
def cleanup() {
}
}