Модификация экземпляров Grails в коллекции - PullRequest
0 голосов
/ 30 октября 2018

Я наблюдаю разное поведение в двух похожих тестах 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() {
    }

}

1 Ответ

0 голосов
/ 30 октября 2018

Почему есть разница, в зависимости от того, какой класс создает объект

Нет разницы в зависимости от того, какой класс создает объект. Проблема не связана с тем, где создаются экземпляры. Проблема в том, что в addObject() вы создаете 2 отдельных объекта, добавляя один из них к objects1, а другой к objects2. В addObject(MyTestObject) вы добавляете один и тот же экземпляр MyTestObject к каждому из 2 Map.

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)
}

Если вы измените addObject() так, ваши тесты будут проходить каждый раз:

void addObject(){
    int count = objects1.size()
    def newTestObject = new MyTestObject()
    objects1.put(count, newTestObject)
    objects2.put(count, newTestObject)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...