001 /** 002 * Copyright 2004-2013 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.student.mock.mojo; 017 018 import org.kuali.student.contract.model.MessageStructure; 019 import org.kuali.student.contract.model.Service; 020 import org.kuali.student.contract.model.ServiceContractModel; 021 import org.kuali.student.contract.model.ServiceMethod; 022 import org.kuali.student.contract.model.ServiceMethodError; 023 import org.kuali.student.contract.model.ServiceMethodParameter; 024 import org.kuali.student.contract.model.util.ServicesFilter; 025 import org.kuali.student.contract.writer.service.GetterSetterNameCalculator; 026 import org.slf4j.Logger; 027 import org.slf4j.LoggerFactory; 028 029 import javax.management.OperationsException; 030 031 import java.util.ArrayList; 032 import java.util.List; 033 034 /** 035 * This class will generate the base class that does CRUD tests as 036 * part of the Conformance Tests for services. The generated class will 037 * need to be extended (and abstract methods filled in) to be complete. 038 * This class is meant to be generated again and again, and developers 039 * should customize tests in the extended class by extending or overwriting 040 * methods of this class as needed. 041 * 042 * @author Mezba Mahtab (mezba.mahtab@utoronto.ca) 043 */ 044 public class ConformanceTestBaseCrudClassServiceWriter extends MockImplServiceWriter { 045 046 private static final Logger log = LoggerFactory.getLogger(ConformanceTestExtendedCrudClassServiceWriter.class); 047 048 ///////////////////////// 049 // CONSTANTS 050 ///////////////////////// 051 052 public static final String ROOT_PACKAGE = "org.kuali.student"; 053 protected static final String H1_COMMENT_CHAR = "="; 054 protected static final int H1_COMMENT_MARK_LENGTH = 20; 055 056 //////////////////////////// 057 // Data Variables 058 //////////////////////////// 059 060 private ServicesFilter filter; 061 062 List<String> dtoObjectNamesWithCrud = null; // a list of all the DTOs managed by this class that has CRUDs 063 064 protected List<String> getDtoObjectNamesWithCrud() { 065 return dtoObjectNamesWithCrud; 066 } 067 068 //////////////////////////// 069 // CONSTRUCTOR 070 //////////////////////////// 071 072 public ConformanceTestBaseCrudClassServiceWriter(ServiceContractModel model, 073 String directory, 074 String rootPackage, 075 String servKey, 076 List<ServiceMethod> methods, 077 boolean isR1) { 078 super(model, directory, rootPackage, servKey, methods, isR1, calcPackage(servKey, rootPackage), calcClassName(servKey)); 079 dtoObjectNamesWithCrud = calcNamesOfDTOsWithCrudManagedByService(); 080 } 081 082 public ConformanceTestBaseCrudClassServiceWriter(ServiceContractModel model, 083 String directory, 084 String rootPackage, 085 String servKey, 086 List<ServiceMethod> methods, 087 boolean isR1, 088 String packageName, 089 String className) { 090 super(model, directory, rootPackage, servKey, methods, isR1, packageName, className); 091 dtoObjectNamesWithCrud = calcNamesOfDTOsWithCrudManagedByService(); 092 } 093 094 ////////////////////////// 095 // FUNCTIONALS 096 ////////////////////////// 097 098 public static String calcPackage(String servKey, String rootPackage) { 099 String pack = rootPackage + "."; 100 pack = pack + "service.test"; 101 return pack; 102 } 103 104 /** 105 * Given the service key (name), returns a calculated class name for the conformance tester. 106 */ 107 public static String calcClassName(String servKey) { 108 return "Test" + GetterSetterNameCalculator.calcInitUpper(fixServKey(servKey) + "ServiceImplConformanceBaseCrud"); 109 } 110 111 public static List<Service> filterServices(ServiceContractModel model, ServicesFilter filter) { 112 if (filter == null) { 113 return model.getServices(); 114 } 115 return filter.filter(model.getServices()); 116 } 117 118 119 /** 120 * Write out the entire file 121 */ 122 public void write() { 123 // begin file 124 indentPrintln("@RunWith(SpringJUnit4ClassRunner.class)"); 125 indentPrintln("@ContextConfiguration(locations = {\"classpath:" + servKey + "-test-with-mock-context.xml\"})"); 126 indentPrint("public abstract class " + calcClassName(servKey) + " "); 127 // println(" implements " + calcServiceInterfaceClassName(servKey)); 128 Service serv = finder.findService(servKey); 129 setPackageName(serv.getImplProject() + ".impl"); // change the package name 130 importsAdd(serv.getImplProject() + "." + serv.getName()); // import for the service 131 132 doTestImportsAdd(); 133 134 // begin main class 135 openBrace(); 136 137 indentPrintln(""); 138 indentPrintDecoratedComment("SETUP", H1_COMMENT_CHAR, H1_COMMENT_MARK_LENGTH); 139 indentPrintln(""); 140 141 // test service setup 142 indentPrintln("@Resource"); 143 indentPrintln("public " + calcServiceInterfaceClassName(servKey) + " testService;"); 144 indentPrintln("public " + calcServiceInterfaceClassName(servKey) + " get" + calcServiceInterfaceClassName(servKey) + "() { return testService; }"); 145 indentPrintln("public void set" + calcServiceInterfaceClassName(servKey) + "(" + calcServiceInterfaceClassName(servKey) + " service) { testService = service; }"); 146 indentPrintln(""); 147 148 // context info setup 149 indentPrintln("public ContextInfo contextInfo = null;"); 150 indentPrintln("public static String principalId = \"123\";"); 151 indentPrintln(""); 152 indentPrintln("@Before"); 153 indentPrintln("public void setUp()"); 154 openBrace(); 155 indentPrintln("principalId = \"123\";"); 156 indentPrintln("contextInfo = new ContextInfo();"); 157 indentPrintln("contextInfo.setPrincipalId(principalId);"); 158 closeBrace(); 159 indentPrintln(""); 160 161 // testing starts 162 indentPrintDecoratedComment("TESTING", H1_COMMENT_CHAR, H1_COMMENT_MARK_LENGTH); 163 indentPrintln(""); 164 /* 165 new ArrayList<String>(); 166 for (ServiceMethod method: methods) { 167 // I am assuming all the DTOs will have a createXXX method. 168 if (MethodType.CREATE.equals (calcMethodType(method))) { 169 String objectName = calcObjectName(method); 170 dtoObjectNames.add(objectName); 171 } 172 } 173 */ 174 // for each DTO, write the testCRUD 175 for (String dtoObjectName : dtoObjectNamesWithCrud) { 176 writeTestCrud(dtoObjectName); 177 indentPrintln(""); 178 } 179 180 // print out list of service operations that were tested 181 indentPrintDecoratedComment("SERVICE OPS TESTED IN BASE TEST CLASS", H1_COMMENT_CHAR, H1_COMMENT_MARK_LENGTH*2); 182 indentPrintln(""); 183 184 // separate out crud and non-crud methods 185 List<ServiceMethod> methodsTestedAsCrud = new ArrayList<ServiceMethod>(); 186 List<ServiceMethod> methodsNotTested = new ArrayList<ServiceMethod>(); 187 188 for (ServiceMethod method : methods) { 189 if (isServiceMethodTestedAsPartofCrudInBaseConformanceTest (method)) { 190 methodsTestedAsCrud.add(method); 191 } else { 192 methodsNotTested.add(method); 193 } 194 } 195 196 // print out crud methods 197 indentPrintln("/*"); 198 incrementIndent(); 199 indentPrintln("The following methods are tested as part of CRUD operations for this service's DTOs:"); 200 incrementIndent(); 201 for (ServiceMethod method: methodsTestedAsCrud) { 202 indentPrintln(method.getName()); 203 } 204 decrementIndent(); 205 decrementIndent(); 206 indentPrintln("*/"); 207 indentPrintln(""); 208 209 // print out list of service operations that are not tested as abstract test methods 210 indentPrintDecoratedComment("SERVICE OPS NOT TESTED IN BASE TEST CLASS", H1_COMMENT_CHAR, H1_COMMENT_MARK_LENGTH*2); 211 indentPrintln(""); 212 213 // for each method, create an abstract method to test that and print it out 214 for (ServiceMethod method: methodsNotTested) { 215 indentPrintln("/* Method Name: " + method.getName() + " */"); 216 indentPrintln("@Test"); 217 indentPrintln("public abstract void test_" + method.getName() + "() "); 218 if (method.getErrors().size()>0) { 219 indentPrint("throws "); 220 String comma = ""; 221 for (ServiceMethodError error: method.getErrors()) { 222 indentPrint(comma + error.getClassName().trim()); 223 comma = ","; 224 } 225 } 226 indentPrintln(";"); 227 indentPrintln(""); 228 } 229 230 // end file print out 231 closeBrace (); 232 println (""); 233 234 // close and print file 235 this.writeJavaClassAndImportsOutToFile(); 236 this.getOut().close(); 237 } 238 239 /** 240 * Write the CRUD test methods 241 */ 242 public void writeTestCrud (String dtoObjectName) { 243 244 // get the message structures of the dto 245 List<MessageStructure> messageStructures = finder.findMessageStructures(dtoObjectName + "Info"); 246 247 // start method open signature 248 indentPrintln("// ****************************************************"); 249 indentPrintln("// " + dtoObjectName + "Info"); 250 indentPrintln("// ****************************************************"); 251 indentPrintln("@Test"); 252 indentPrintln("public void testCrud" + dtoObjectName + "() "); 253 incrementIndent(); 254 indentPrintln("throws DataValidationErrorException,"); 255 incrementIndent(); 256 indentPrintln("DoesNotExistException,"); 257 indentPrintln("InvalidParameterException,"); 258 indentPrintln("MissingParameterException,"); 259 indentPrintln("OperationFailedException,"); 260 indentPrintln("PermissionDeniedException,"); 261 indentPrintln("ReadOnlyException,"); 262 indentPrintln("VersionMismatchException,"); 263 indentPrintln("DependentObjectsExistException"); 264 decrementIndent(); 265 decrementIndent(); 266 openBrace(); 267 // end method open signature 268 269 // write the test portions 270 incrementIndent(); 271 writeTestCreate(dtoObjectName, messageStructures); 272 writeTestUpdate(dtoObjectName, messageStructures); 273 writeTestReadAfterUpdate(dtoObjectName, messageStructures); 274 writeTestDelete(dtoObjectName, messageStructures); 275 decrementIndent(); 276 277 // end method 278 closeBrace(); 279 indentPrintln(""); 280 281 // methods that will be overwritten 282 writetestCrudXXX_setDTOFieldsForTestCreate(dtoObjectName, messageStructures); 283 writetestCrudXXX_testDTOFieldsForTestCreateUpdate(dtoObjectName, messageStructures); 284 writetestCrudXXX_setDTOFieldsForTestUpdate(dtoObjectName, messageStructures); 285 writetestCrudXXX_testDTOFieldsForTestReadAfterUpdate(dtoObjectName, messageStructures); 286 writetestCrudXXX_setDTOFieldsForTestReadAfterUpdate(dtoObjectName, messageStructures); 287 } 288 289 /** 290 * Write the 'test create' portion. 291 */ 292 public void writeTestCreate (String dtoObjectName, List<MessageStructure> messageStructures) { 293 indentPrintDecoratedComment("test create"); 294 indentPrintln(dtoObjectName + "Info expected = new " + dtoObjectName + "Info ();"); 295 // indentPrintln("expected.setName(\"Name01\");"); 296 // indentPrintln("expected.setDescr(new RichTextHelper().fromPlain(\"Description01\"));"); 297 indentPrintln(""); 298 indentPrintln("// METHOD TO SET DTO FIELDS HERE FOR TEST CREATE"); 299 indentPrintln("testCrud" + dtoObjectName + "_setDTOFieldsForTestCreate (expected);"); 300 indentPrintln(""); 301 302 /* 303 indentPrintln("if (expected.getClass().isAssignableFrom(TypeStateEntityInfo.class))"); 304 openBrace(); 305 incrementIndent(); 306 // indentPrintln("TypeStateEntityInfo expectedTS = (TypeStateEntityInfo) expected;"); 307 indentPrintln("expected.setTypeKey(\"typeKey01\");"); 308 indentPrintln("expected.setStateKey(\"stateKey01\");"); 309 decrementIndent(); 310 closeBrace(); 311 */ 312 indentPrintln("new AttributeTester().add2ForCreate(expected.getAttributes());"); 313 314 indentPrintln(""); 315 indentPrintln("// code to create actual"); 316 indentPrintln(dtoObjectName + "Info actual = " + getMethodCallAsString ("create" + dtoObjectName, "= null; // TODO INSERT CODE TO CREATE actual HERE", MethodType.CREATE, dtoObjectName, "expected")); 317 indentPrintln(""); 318 319 // indentPrintln("if (actual.getClass().isAssignableFrom(IdEntityInfo.class))"); 320 if (finder.findMessageStructure(dtoObjectName + "Info", "id")!=null) { 321 // openBrace(); 322 // incrementIndent(); 323 indentPrintln("assertNotNull(actual.getId());"); 324 indentPrintln("new IdEntityTester().check(expected, actual);"); 325 // decrementIndent(); 326 // closeBrace(); 327 } 328 else if (finder.findMessageStructure(dtoObjectName + "Info", "key")!=null) { 329 indentPrintln("assertNotNull(actual.getKey());"); 330 indentPrintln("new KeyEntityTester().check(expected, actual);"); 331 } 332 333 indentPrintln(""); 334 indentPrintln("// METHOD TO TEST DTO FIELDS HERE FOR TEST CREATE"); 335 indentPrintln("testCrud" + dtoObjectName + "_testDTOFieldsForTestCreateUpdate (expected, actual);"); 336 indentPrintln(""); 337 338 indentPrintln("new AttributeTester().check(expected.getAttributes(), actual.getAttributes());"); 339 indentPrintln("new MetaTester().checkAfterCreate(actual.getMeta());"); 340 indentPrintln(""); 341 342 indentPrintDecoratedComment("test read"); 343 indentPrintln("expected = actual;"); 344 indentPrintln("actual = " + getMethodCallAsString ("get" + dtoObjectName, "null; // TODO INSERT CODE TO GET actual HERE BY CALLING SERVICE OP", MethodType.GET_BY_ID, dtoObjectName, "actual")); 345 if (finder.findMessageStructure(dtoObjectName + "Info", "id")!=null) { 346 indentPrintln("assertEquals(expected.getId(), actual.getId());"); 347 indentPrintln("new IdEntityTester().check(expected, actual);"); 348 } 349 else if (finder.findMessageStructure(dtoObjectName + "Info", "key")!=null) { 350 indentPrintln("assertEquals(expected.getKey(), actual.getKey());"); 351 indentPrintln("new KeyEntityTester().check(expected, actual);"); 352 } 353 354 355 indentPrintln(""); 356 357 indentPrintln("// INSERT CODE FOR TESTING MORE DTO FIELDS HERE"); 358 indentPrintln("testCrud" + dtoObjectName + "_testDTOFieldsForTestCreateUpdate (expected, actual);"); 359 indentPrintln(""); 360 361 indentPrintln("new AttributeTester().check(expected.getAttributes(), actual.getAttributes());"); 362 indentPrintln("new MetaTester().checkAfterGet(expected.getMeta(), actual.getMeta());"); 363 indentPrintln(""); 364 } 365 366 /** 367 * Write the 'test update' portion. 368 */ 369 public void writeTestUpdate (String dtoObjectName, List<MessageStructure> messageStructures) { 370 indentPrintDecoratedComment("test update"); 371 indentPrintln(dtoObjectName + "Info original = new " + dtoObjectName + "Info (actual);"); 372 indentPrintln("expected = new " + dtoObjectName + "Info (actual);"); 373 374 // indentPrintln("expected.setName(expected.getName() + \" updated\");"); 375 // indentPrintln("expected.setDescr(new RichTextHelper().fromPlain(expected.getDescr().getPlain() + \"_Updated\"));"); 376 indentPrintln(""); 377 // indentPrintln("if (expected.getClass().isAssignableFrom(TypeStateEntityInfo.class))"); 378 if (finder.findMessageStructure(dtoObjectName + "Info", "stateKey")!=null) { 379 // openBrace(); 380 // incrementIndent(); 381 // indentPrintln("TypeStateEntityInfo expectedTS = (TypeStateEntityInfo) expected;"); 382 indentPrintln("expected.setStateKey(expected.getState() + \"_Updated\");"); 383 // decrementIndent(); 384 // closeBrace(); 385 } 386 indentPrintln(""); 387 indentPrintln("// METHOD TO INSERT CODE TO UPDATE DTO FIELDS HERE"); 388 indentPrintln("testCrud" + dtoObjectName + "_setDTOFieldsForTestUpdate (expected);"); 389 indentPrintln(""); 390 indentPrintln("new AttributeTester().delete1Update1Add1ForUpdate(expected.getAttributes());"); 391 392 indentPrintln("// code to update"); 393 indentPrintln("actual = " + getMethodCallAsString ("update" + dtoObjectName, "= null; // TODO INSERT CODE TO CALL UPDATE SERVICE OP HERE", MethodType.UPDATE, dtoObjectName, "expected")); 394 indentPrintln(""); 395 396 if (finder.findMessageStructure(dtoObjectName + "Info", "id")!=null) { 397 indentPrintln("assertEquals(expected.getId(), actual.getId());"); 398 indentPrintln("new IdEntityTester().check(expected, actual);"); 399 } 400 else if (finder.findMessageStructure(dtoObjectName + "Info", "key")!=null) { 401 indentPrintln("assertEquals(expected.getKey(), actual.getKey());"); 402 indentPrintln("new KeyEntityTester().check(expected, actual);"); 403 } 404 indentPrintln(""); 405 indentPrintln("// METHOD TO INSERT CODE FOR TESTING DTO FIELDS HERE"); 406 indentPrintln("testCrud" + dtoObjectName + "_testDTOFieldsForTestCreateUpdate (expected, actual);"); 407 indentPrintln(""); 408 indentPrintln("new AttributeTester().check(expected.getAttributes(), actual.getAttributes());"); 409 indentPrintln("new MetaTester().checkAfterUpdate(expected.getMeta(), actual.getMeta());"); 410 indentPrintln(""); 411 412 indentPrintln("// Test that VersionMissmatchException's are being detected"); 413 indentPrintln("boolean exception = false;"); 414 indentPrintln("try {"); 415 indent(getOut(), ' '); 416 417 indentPrintln(getMethodCallAsString ("update" + dtoObjectName, "= null; // TODO INSERT CODE TO CALL UPDATE SERVICE OP HERE", MethodType.UPDATE, dtoObjectName, "original")); 418 indentPrintln("}"); 419 indentPrintln("catch (VersionMismatchException e) { "); 420 indent(getOut(), ' '); 421 indentPrint("exception = true;"); 422 indentPrintln("}"); 423 indentPrintln(""); 424 425 indentPrintln("Assert.assertTrue(\"VersionMissmatchException was not detected!\", exception);"); 426 indentPrintln(""); 427 428 } 429 430 /** 431 * Write the 'read after update' portion. 432 */ 433 public void writeTestReadAfterUpdate (String dtoObjectName, List<MessageStructure> messageStructures) { 434 indentPrintDecoratedComment("test read after update"); 435 indentPrintln(""); 436 indentPrintln("expected = actual;"); 437 438 indentPrintln("// code to get actual"); 439 indentPrintln("actual = " + getMethodCallAsString ("get" + dtoObjectName, "null; // TODO INSERT CODE TO GET actual HERE BY CALLING SERVICE OP", MethodType.GET_BY_ID, dtoObjectName, "actual")); 440 indentPrintln(""); 441 if (finder.findMessageStructure(dtoObjectName + "Info", "id")!=null) { 442 indentPrintln("assertEquals(expected.getId(), actual.getId());"); 443 indentPrintln("new IdEntityTester().check(expected, actual);"); 444 } 445 else if (finder.findMessageStructure(dtoObjectName + "Info", "key")!=null) { 446 indentPrintln("assertEquals(expected.getKey(), actual.getKey());"); 447 indentPrintln("new KeyEntityTester().check(expected, actual);"); 448 } 449 indentPrintln(""); 450 indentPrintln("// INSERT METHOD CODE FOR TESTING DTO FIELDS HERE"); 451 indentPrintln("testCrud" + dtoObjectName + "_testDTOFieldsForTestReadAfterUpdate (expected, actual);"); 452 indentPrintln(""); 453 indentPrintln("new AttributeTester().check(expected.getAttributes(), actual.getAttributes());"); 454 indentPrintln("new MetaTester().checkAfterGet(expected.getMeta(), actual.getMeta());"); 455 indentPrintln(""); 456 indentPrintln(dtoObjectName + "Info alphaDTO = actual;"); 457 indentPrintln(""); 458 indentPrintln("// create a 2nd DTO"); 459 indentPrintln(dtoObjectName + "Info betaDTO = new " + dtoObjectName + "Info ();"); 460 // indentPrintln("betaDTO.setName(\"Beta entity name\");"); 461 // indentPrintln("betaDTO.setDescr(new RichTextHelper().fromPlain(\"Beta entity description\"));"); 462 indentPrintln(""); 463 indentPrintln("// METHOD TO INSERT CODE TO SET MORE DTO FIELDS HERE"); 464 indentPrintln("testCrud" + dtoObjectName + "_setDTOFieldsForTestReadAfterUpdate (betaDTO);"); 465 indentPrintln(""); 466 // indentPrintln("if (betaDTO.getClass().isAssignableFrom(TypeStateEntityInfo.class))"); 467 if (finder.findMessageStructure(dtoObjectName + "Info", "typeKey")!=null) { 468 // openBrace(); 469 // incrementIndent(); 470 //indentPrintln("TypeStateEntityInfo betaDTOTS = (TypeStateEntityInfo) betaDTO;"); 471 indentPrintln("betaDTO.setTypeKey(\"typeKeyBeta\");"); 472 // decrementIndent(); 473 // closeBrace(); 474 } 475 if (finder.findMessageStructure(dtoObjectName + "Info", "stateKey")!=null) { 476 indentPrintln("betaDTO.setStateKey(\"stateKeyBeta\");"); 477 } 478 indentPrintln("betaDTO = " + getMethodCallAsString("create" + dtoObjectName, "null; // TODO INSERT CODE TO CREATE betaDTO", MethodType.CREATE, dtoObjectName, "betaDTO")); 479 480 indentPrintln(""); 481 indentPrintDecoratedComment("test bulk get with no ids supplied"); 482 indentPrintln(""); 483 indentPrintln("List<String> " + initLower(dtoObjectName) + "Ids = new ArrayList<String>();"); 484 485 indentPrintln("// code to get DTO by Ids"); 486 indentPrintln("List<" + dtoObjectName + "Info> records = " + getMethodCallAsString ("get" + dtoObjectName + "sByIds", "null; // TODO INSERT CODE TO GET DTO BY IDS", MethodType.GET_BY_IDS, dtoObjectName)); 487 indentPrintln(""); 488 489 indentPrintln("assertEquals(" + initLower(dtoObjectName) + "Ids.size(), records.size());"); 490 indentPrintln("assertEquals(0, " + initLower(dtoObjectName) + "Ids.size());"); 491 indentPrintln(""); 492 indentPrintDecoratedComment("test bulk get"); 493 indentPrintln(initLower(dtoObjectName) + "Ids = new ArrayList<String>();"); 494 indentPrintln(initLower(dtoObjectName) + "Ids.add(alphaDTO.getId());"); 495 indentPrintln(initLower(dtoObjectName) + "Ids.add(betaDTO.getId());"); 496 497 indentPrintln("// code to get DTO by Ids"); 498 indentPrintln("records = " + getMethodCallAsString ("get" + dtoObjectName + "sByIds", "null; // TODO INSERT CODE TO GET DTO BY IDS", MethodType.GET_BY_IDS, dtoObjectName)); 499 indentPrintln(""); 500 501 indentPrintln("assertEquals(" + initLower(dtoObjectName) + "Ids.size(), records.size());"); 502 indentPrintln("for (" + dtoObjectName + "Info record : records)"); 503 openBrace(); 504 incrementIndent(); 505 indentPrintln("if (!" + initLower(dtoObjectName) + "Ids.remove(record.getId()))"); 506 openBrace(); 507 incrementIndent(); 508 indentPrintln("fail(record.getId());"); 509 decrementIndent(); 510 closeBrace(); 511 decrementIndent(); 512 closeBrace(); 513 indentPrintln("assertEquals(0, " + initLower(dtoObjectName) + "Ids.size());"); 514 indentPrintln(""); 515 indentPrintDecoratedComment("test get by type"); 516 517 indentPrintln("// code to get by specific type \"typeKey01\" "); 518 indentPrintln(initLower(dtoObjectName) + "Ids = testService.get" + dtoObjectName + "IdsByType (\"typeKey_Updated\", contextInfo);"); 519 // indentPrintln(initLower(dtoObjectName) + "Ids = " + getMethodCallAsString ("get" + dtoObjectName + "IdsByType", "// INSERT CODE TO GET BY SPECIFIC TYPE \"typeKey01\" HERE", MethodType.GET_IDS_BY_TYPE)); 520 indentPrintln(""); 521 522 indentPrintln("assertEquals(1, " + initLower(dtoObjectName) + "Ids.size());"); 523 indentPrintln("assertEquals(alphaDTO.getId(), " + initLower(dtoObjectName) + "Ids.get(0));"); 524 indentPrintln(""); 525 indentPrintln("// test get by other type"); 526 527 indentPrintln("// code to get by specific type \"typeKeyBeta\" "); 528 indentPrintln(initLower(dtoObjectName) + "Ids = testService.get" + dtoObjectName + "IdsByType (\"typeKeyBeta\", contextInfo);"); 529 // indentPrintln(initLower(dtoObjectName) + "Ids = " + getMethodCallAsString ("get" + dtoObjectName + "IdsByType", "// INSERT CODE TO GET BY SPECIFIC TYPE \"typeKeyBeta\" HERE", MethodType.GET_IDS_BY_TYPE)); 530 indentPrintln(""); 531 532 indentPrintln("assertEquals(1, " + initLower(dtoObjectName) + "Ids.size());"); 533 indentPrintln("assertEquals(betaDTO.getId(), " + initLower(dtoObjectName) + "Ids.get(0));"); 534 indentPrintln(""); 535 } 536 537 /** 538 * Write the 'delete' portion. 539 */ 540 public void writeTestDelete (String dtoObjectName, List<MessageStructure> messageStructures) { 541 indentPrintDecoratedComment("test delete"); 542 indentPrintln(""); 543 544 indentPrintln("StatusInfo status = " + getMethodCallAsString ("delete" + dtoObjectName, "null; // TODO INSERT CODE TO DELETE RECORD", MethodType.DELETE, dtoObjectName, "actual")); 545 indentPrintln(""); 546 547 indentPrintln("assertNotNull(status);"); 548 indentPrintln("assertTrue(status.getIsSuccess());"); 549 indentPrintln("try"); 550 openBrace(); 551 incrementIndent(); 552 indentPrintln(dtoObjectName + "Info record = " + getMethodCallAsString ("get" + dtoObjectName, "null; // TODO INSERT CODE TO RETRIEVE RECENTLY DELETED RECORD", MethodType.GET_BY_ID, dtoObjectName, "actual")); 553 indentPrintln("fail(\"Did not receive DoesNotExistException when attempting to get already-deleted entity\");"); 554 decrementIndent(); 555 closeBrace(); 556 indentPrintln("catch (DoesNotExistException dnee)"); 557 openBrace(); 558 incrementIndent(); 559 indentPrintln("// expected"); 560 decrementIndent(); 561 closeBrace(); 562 indentPrintln(""); 563 } 564 565 /** 566 * Writes out a decorated comment. 567 */ 568 public void indentPrintDecoratedComment (String label) { 569 indentPrintDecoratedComment(label, "-", 37); 570 /* 571 indentPrintln("// -------------------------------------"); 572 indentPrintln("// " + label); 573 indentPrintln("// -------------------------------------"); 574 */ 575 } 576 577 /** 578 * Writes out a decorated comment, with the decoration string passed in. 579 */ 580 public void indentPrintDecoratedComment (String label, String decorChar, int decorLength) { 581 String decorPattern = ""; 582 for (int i=0; i<decorLength; i++) { decorPattern += decorChar; } 583 indentPrintln("// " + decorPattern); 584 indentPrintln("// " + label); 585 indentPrintln("// " + decorPattern); 586 } 587 588 /** 589 * Gets the method with the name. 590 */ 591 private ServiceMethod getServiceMethod (String methodName) throws OperationsException { 592 for (ServiceMethod method : methods) { 593 if (method.getName().equals(methodName)) return method; 594 } 595 throw new OperationsException("Method " + methodName + " not found!"); 596 } 597 598 /** 599 * Gets the string to print to call a method with the given name. 600 * @param dtoObjectName 601 */ 602 private String getMethodCallAsString (String builtUpMethodName, String errorCode, MethodType methodType, String dtoObjectName) { 603 return getMethodCallAsString (builtUpMethodName, errorCode, methodType, dtoObjectName, null); 604 } 605 606 /** 607 * Gets the string to print to call a method with the given name. 608 */ 609 private String getMethodCallAsString (String builtUpMethodName, String errorCode, MethodType methodType, String dtoName, String dtoNameReplacement) { 610 try { 611 ServiceMethod method = getServiceMethod(builtUpMethodName); 612 String methodCallStr = ""; 613 methodCallStr += method.getName() + " ("; 614 String comma = " "; 615 for (ServiceMethodParameter param : method.getParameters()) { 616 methodCallStr += comma; 617 if (dtoName!=null && dtoNameReplacement!=null) { 618 if ((dtoName + "Info").toLowerCase().equals(param.getName().toLowerCase())) { 619 methodCallStr += dtoNameReplacement; 620 } 621 else if (param.getName().endsWith("TypeKey")) { 622 methodCallStr += dtoNameReplacement + ".getTypeKey()"; 623 } 624 else if (param.getName().endsWith("Id")) { 625 methodCallStr += dtoNameReplacement + ".getId()"; 626 } 627 else { 628 methodCallStr += param.getName(); 629 } 630 } else { 631 methodCallStr += param.getName(); 632 } 633 comma = ", "; 634 } 635 methodCallStr += ");"; 636 return "testService." + methodCallStr; 637 } catch (Exception e) { 638 639 if (dtoName != null) 640 log.error("dtoName = " + dtoName + ", methodName = " + builtUpMethodName + ", errorCode = " + errorCode); 641 else 642 log.error("dtoName = unknown, methodName = " + builtUpMethodName + ", errorCode = " + errorCode); 643 644 return errorCode; 645 } 646 647 } 648 649 /** 650 * Writes the section to set fields specific to this dto for testCreate section. 651 */ 652 public void writetestCrudXXX_setDTOFieldsForTestCreate(String dtoObjectName, List<MessageStructure> messageStructures) { 653 indentPrintln("/*"); 654 incrementIndent(); 655 indentPrintln("A method to set the fields for a " + dtoObjectName + " in a 'test create' section prior to calling the 'create' operation."); 656 decrementIndent(); 657 indentPrintln("*/"); 658 indentPrintln("public abstract void testCrud" + dtoObjectName + "_setDTOFieldsForTestCreate(" + dtoObjectName + "Info expected);"); 659 indentPrintln(""); 660 } 661 662 /** 663 * Writes the section to test fields specific to this dto for testCreate and testUpdate sections. 664 */ 665 public void writetestCrudXXX_testDTOFieldsForTestCreateUpdate(String dtoObjectName, List<MessageStructure> messageStructures) { 666 indentPrintln("/*"); 667 incrementIndent(); 668 indentPrintln("A method to test the fields for a " + dtoObjectName + ". This is called after:"); 669 indentPrintln("- creating a DTO, where actual is the DTO returned by the create operation, and expected is the dto passed in to the create operation"); 670 indentPrintln("- reading a DTO after creating it, and actual is the read DTO, and expected is the dto that was created"); 671 indentPrintln("- updating a DTO, where actual is DTO returned by the update operation, and expected is the dto that was passed in to the update operation"); 672 decrementIndent(); 673 indentPrintln("*/"); 674 indentPrintln("public abstract void testCrud" + dtoObjectName + "_testDTOFieldsForTestCreateUpdate(" + dtoObjectName + "Info expected, " + dtoObjectName + "Info actual);"); 675 indentPrintln(""); 676 } 677 678 679 /** 680 * Writes the section to set fields specific to this dto for testUpdate sections. 681 */ 682 public void writetestCrudXXX_setDTOFieldsForTestUpdate(String dtoObjectName, List<MessageStructure> messageStructures) { 683 indentPrintln("/*"); 684 incrementIndent(); 685 indentPrintln("A method to set the fields for a " + dtoObjectName + " in a 'test update' section prior to calling the 'update' operation."); 686 decrementIndent(); 687 indentPrintln("*/"); 688 indentPrintln("public abstract void testCrud" + dtoObjectName + "_setDTOFieldsForTestUpdate(" + dtoObjectName + "Info expected);"); 689 indentPrintln(""); 690 } 691 692 /** 693 * Writes the section to test fields specific to this dto for testReadAfterUpdate sections. 694 */ 695 public void writetestCrudXXX_testDTOFieldsForTestReadAfterUpdate(String dtoObjectName, List<MessageStructure> messageStructures) { 696 indentPrintln("/*"); 697 incrementIndent(); 698 indentPrintln("A method to test the fields for a " + dtoObjectName + " after an update operation, followed by a read operation,"); 699 indentPrintln("where actual is the DTO returned by the read operation, and expected is the dto returned by the update operation."); 700 decrementIndent(); 701 indentPrintln("*/"); 702 indentPrintln("public abstract void testCrud" + dtoObjectName + "_testDTOFieldsForTestReadAfterUpdate(" + dtoObjectName + "Info expected, " + dtoObjectName + "Info actual);"); 703 indentPrintln(""); 704 } 705 706 /** 707 * Writes the section to set fields specific to this dto for testReadAfterUpdate sections. 708 */ 709 public void writetestCrudXXX_setDTOFieldsForTestReadAfterUpdate(String dtoObjectName, List<MessageStructure> messageStructures) { 710 indentPrintln("/*"); 711 incrementIndent(); 712 indentPrintln("A method to set the fields for a " + dtoObjectName + " in the 'test read after update' section."); 713 indentPrintln("This dto is another (second) dto object being created for other tests."); 714 decrementIndent(); 715 indentPrintln("*/"); 716 indentPrintln("public abstract void testCrud" + dtoObjectName + "_setDTOFieldsForTestReadAfterUpdate(" + dtoObjectName + "Info expected);"); 717 indentPrintln(""); 718 } 719 720 /** 721 * Given a method type, returns true if this method is tested as part of CRUD operations 722 * tested by the base test conformance class. 723 */ 724 protected boolean isServiceMethodTestedAsPartofCrudInBaseConformanceTest (ServiceMethod method) { 725 MethodType methodType = calcMethodType(method); 726 if ((MethodType.CREATE.equals(methodType)) 727 || (MethodType.UPDATE.equals(methodType)) 728 || (MethodType.DELETE.equals(methodType)) 729 || (MethodType.GET_BY_ID.equals(methodType)) 730 || (MethodType.GET_BY_IDS.equals(methodType)) 731 || (MethodType.GET_IDS_BY_TYPE.equals(methodType)) 732 || (MethodType.GET_TYPE.equals(methodType)) 733 || (MethodType.GET_TYPES.equals(methodType)) 734 || (MethodType.GET_IDS_BY_TYPE.equals(methodType)) 735 ) { 736 return true; 737 } else { 738 return false; 739 } 740 741 } 742 743 /** 744 * Gets a list of all the DTO names that are part of this service. 745 */ 746 protected List<String> calcNamesOfDTOsWithCrudManagedByService() { 747 List<String> dtoObjectNames = new ArrayList<String>(); 748 for (ServiceMethod method: methods) { 749 // I am assuming all the DTOs will have a createXXX method. 750 if (MethodType.CREATE.equals (calcMethodType(method))) { 751 String objectName = calcObjectName(method); 752 // check if this is a valid info object 753 if (finder.findXmlType(objectName + "Info")!=null) { 754 dtoObjectNames.add(objectName); 755 } 756 /* 757 for (XmlType xmlType: model.getXmlTypes()) { 758 if (xmlType.getName().equals(objectName + "Info")) { 759 dtoObjectNames.add(objectName); 760 break; 761 } 762 } 763 */ 764 } 765 } 766 return dtoObjectNames; 767 } 768 769 /** 770 * Does the importsAdd for all files required for testing 771 */ 772 protected void doTestImportsAdd() { 773 // kuali imports 774 importsAdd("org.kuali.student.common.test.util.IdEntityTester"); 775 importsAdd("org.kuali.student.common.test.util.KeyEntityTester"); 776 importsAdd("org.kuali.student.r2.common.dto.ContextInfo"); 777 importsAdd("org.kuali.student.r2.common.dto.IdEntityInfo"); 778 importsAdd("org.kuali.student.r2.common.dto.StatusInfo"); 779 importsAdd("org.kuali.student.r2.common.dto.TypeStateEntityInfo"); 780 importsAdd("org.kuali.student.r2.common.util.RichTextHelper"); 781 importsAdd("org.kuali.student.r2.core.organization.service.impl.lib.AttributeTester"); 782 importsAdd("org.kuali.student.r2.core.organization.service.impl.lib.MetaTester"); 783 784 // import all the dto 785 // for each DTO, write the testCRUD 786 for (String dtoObjectName : dtoObjectNamesWithCrud) { 787 try { importsAdd(finder.findXmlType(dtoObjectName + "Info").getJavaPackage() + "." + dtoObjectName + "Info"); } 788 catch (Exception ignored) {} 789 } 790 791 // exceptions 792 importsAdd("org.kuali.student.r2.common.exceptions.DataValidationErrorException"); 793 importsAdd("org.kuali.student.r2.common.exceptions.DependentObjectsExistException"); 794 importsAdd("org.kuali.student.r2.common.exceptions.DoesNotExistException"); 795 importsAdd("org.kuali.student.r2.common.exceptions.InvalidParameterException"); 796 importsAdd("org.kuali.student.r2.common.exceptions.MissingParameterException"); 797 importsAdd("org.kuali.student.r2.common.exceptions.OperationFailedException"); 798 importsAdd("org.kuali.student.r2.common.exceptions.PermissionDeniedException"); 799 importsAdd("org.kuali.student.r2.common.exceptions.ReadOnlyException"); 800 importsAdd("org.kuali.student.r2.common.exceptions.VersionMismatchException"); 801 802 // java imports 803 importsAdd("org.springframework.test.context.ContextConfiguration"); 804 importsAdd("org.springframework.test.context.junit4.SpringJUnit4ClassRunner"); 805 importsAdd("org.junit.Assert"); 806 importsAdd("org.junit.Before"); 807 importsAdd("org.junit.Test"); 808 importsAdd("org.junit.runner.RunWith"); 809 importsAdd("static org.junit.Assert.assertEquals"); 810 importsAdd("static org.junit.Assert.assertFalse"); 811 importsAdd("static org.junit.Assert.assertNotNull"); 812 importsAdd("static org.junit.Assert.assertNull"); 813 importsAdd("static org.junit.Assert.assertTrue"); 814 importsAdd("static org.junit.Assert.fail"); 815 importsAdd("javax.annotation.Resource"); 816 importsAdd("java.util.ArrayList"); 817 importsAdd("java.util.List"); 818 } 819 }