Java 集合中的Grails实例修改
我在两个类似的Grails3.3.5测试用例中观察到了不同的行为。这两种情况的区别是:Java 集合中的Grails实例修改,java,unit-testing,grails,Java,Unit Testing,Grails,我在两个类似的Grails3.3.5测试用例中观察到了不同的行为。这两种情况的区别是: 在第一个测试用例中,规范创建一个测试对象,将其交给控制器,控制器将其添加/放入他的两个集合objects1和objects2。在等级库中修改对象时,更改同时适用于objects1和objects2 在第二个测试用例中,控制器本身创建一个对象,并将其放入他的两个集合中。当我要求控制器从第一个集合(objects1)交付对象,然后在规范中修改此对象时,更改仅应用于objects1,而不应用于其他集合object
- 在第一个测试用例中,规范创建一个测试对象,将其交给控制器,控制器将其添加/放入他的两个集合
和objects1
。在等级库中修改对象时,更改同时适用于objects2
和objects1
objects2
- 在第二个测试用例中,控制器本身创建一个对象,并将其放入他的两个集合中。当我要求控制器从第一个集合(
)交付对象,然后在规范中修改此对象时,更改仅应用于objects1
,而不应用于其他集合objects1
objects2
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)
}
}
类MyTestController{
def index(){}
映射对象1
映射对象2
MyTestController(){
objects1=新的HashMap()
objects2=新的HashMap()
}
void addObject(){
int count=objects1.size()
objects1.put(计数,新的MyTestObject())
objects2.put(计数,新的MyTestObject())
}
void addObject(MyTestObject testObject){
int count=objects1.size()
objects1.put(count,testObject)
objects2.put(计数,testObject)
}
MyTestObject getObjectFromCollection1(int-atPosition){
如果(0>atPosition | | atPosition>objects1.size()-1){
回来
}
objects1.get(atPosition)
}
MyTestObject getObjectFromCollection2(int-atPosition){
如果(0>atPosition | | atPosition>objects2.size()-1){
回来
}
objects2.get(atPosition)
}
void updateObjectInCollection1(int索引,MyTestObject对象){
objects1.put(索引,对象)
}
}
规格为:
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() {
}
}
导入grails.testing.web.controllers.ControllerUnitTest
导入spock.lang.Specification
类MyTestControllerSpec扩展规范实现ControllerUnitTest{
整数索引
def设置(){
索引=0
}
无效“案例1:外部对象实例化”(){
MyTestController控制器本地=新的MyTestController()
MyTestObject对象=新的MyTestObject()
controllerLocal.addObject(对象)
object.edit()
MyTestObject afterEditInCollection1=controllerLocal.getObjectFromCollection1(索引)
MyTestObject afterEditInCollection2=controllerLocal.getObjectFromCollection2(索引)
期望:
“已编辑”==object.getValue()
“已编辑”==afterEditInCollection1.getValue()
“已编辑”==afterEditInCollection2.getValue()
}
无效“案例2:内部对象实例化”(){
MyTestController控制器本地=新的MyTestController()
controllerLocal.addObject()
MyTestObject ToBeedItemLocally=controllerLocal.getObjectFromCollection1(索引)
toBeEditedLocally.edit()
MyTestObject afterEditInCollection1=controllerLocal.getObjectFromCollection1(索引)
MyTestObject afterEditInCollection2=controllerLocal.getObjectFromCollection2(索引)
期望:
“已编辑”==toBeEditedLocally.getValue()
“已编辑”==afterEditInCollection1.getValue()
“已编辑”==afterEditInCollection2.getValue()
}
def cleanup(){
}
}
为什么会有差异,这取决于创建
反对
这与创建对象的类没有区别。问题与实例的创建位置无关。问题在于,在addObject()
中,您正在创建两个单独的对象,将其中一个添加到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)
}
这与您的问题无关,但是在单例控制器中使用那些
object1
和object2
实例变量可能会导致并发问题。很难从您的示例中看出您实际使用它们的目的,但控制器中不会有这些功能。@JeffScottBrown是的,谢谢您的提示。这只是一个澄清的例子-我要记住这一点。哦,我真蠢。有时你需要另一双眼睛。谢谢“哦,愚蠢的我”-一点也不愚蠢。很高兴这有道理。祝你好运!