2016-11-06 6 views
0

Ich schreibe einen einfachen Integrationstest, bei dem ich Löschfehler simulieren möchte.Wie überschreiben gorm delete-Methode zum Testen?

Der Controller zieht den Datensatz einfach aus der Datenbank und löscht ihn wie unten gezeigt.

def deleteItem(id){ 


    def item = Item.get(id) 

    item.delete() 

} 

Nun, ich will Ausfall simulieren löschen mit Code folgenden

void testDeleteItem_FailDeleteFlushSaveFail(){ 


    Item.metaClass.delete = { Map params -> 

     throw new ValidationException("Failed!!") 

    } 



    def model = controller.deleteItem(mp.id) 


    assertEquals controller.flash.message, "Sorry an error occured when deleting!!" 



    GroovySystem.metaClassRegistry.removeMetaClass(Item.class) 



} 

Aber der Test schlägt fehl, da das Verfahren nicht ersetzt wird. Die Ausnahme wird nicht auf delete geworfen. Ich vermute, dass das Problem in meiner Metaklassenformulierung liegt. Wie kann ich es so machen, dass beim Löschen eine Ausnahme ausgelöst wird? Ich schätze jede Hilfe! Vielen Dank!

Antwort

-1

Versuchen Sie das mal mit:

Item.metaClass.'static'.delete = { Map params -> 
    throw new ValidationException("Failed!!") 
} 
0

Dies liegt daran, Sie

Item.metaClass.delete = { 

     throw new ValidationException("Failed!!") 

    } 

statt

Item.metaClass.delete = { Map params -> 

     throw new ValidationException("Failed!!") 

    } 
0

Zunächst einmal verwenden sollte, glaube ich nicht die Frage sein sollte down-voting .. Es ist eine gültige Frage für ein Szenario, in dem Sie testen möchten, wie Ihr Programm auf einen Fehler reagiert .

Es gibt ein paar Dinge falsch hier:

  • Domain.delete nicht validationExceptions wirft. Auch ValidationExceptions werden mit zwei Argumenten erstellt (String msg, Errors error). Sie müssten Ihrer Domänenklasse einen benutzerdefinierten Fehler hinzufügen und die Domänenklasse übergeben. Auch dies ist für das Löschen nicht sinnvoll, denn wer muss das Objekt beim Löschen validieren? nicht sicher, welche Version Sie laufen, aber hier ist die Dokumentation für 2.5.1 (Grails 2.5.1 docs -siehe 7.3.2 Löschen von Objekten)

    def p = person.get (1) try { p.delete (flush : true) } catch (org.springframework.dao.DataIntegrityViolationException e) { flash.message = "Konnte Person $ {p.name} nicht löschen" redirect (action: "show", id: p.id) }

  • Zweitens löschen (FailOnError: True). Ich bin mir nicht sicher, ob das irgendwas macht. Stattdessen sollten Sie Ihre Löschmethode in einem try catch umschließen und die Option flush: true verwenden.

    try{ 
        item.delete(flush:true) 
    }catch(DataIntegrityViolationException e){ 
        flash.message = "Sorry an error occurred when deleting!!" 
    } 
    
  • Drittens, woher kommt mp.id? Fehlt uns ein Teil Ihrer Testdatei? Wenn nicht, scheint Ihr Test auf Daten zu beruhen, die bereits existieren. Selbst in einem Integrationstest ist es sinnvoll, Ihre Daten für jeden Test separat zu erstellen, um Testkontaminationen und fehlgeschlagene Tests aufgrund fehlender Daten zu vermeiden.

  • Schließlich war ich nicht in der Lage, die Domänenklasse selbst in meinen Integrationstests korrekt zu kategorisieren ... also würde ich Ihnen empfehlen, die Domäneninstanz in Ihrem Test zu metaClass.Hier ist ein Beispiel dafür:

MetaClass Domain Instanz Methode:

//creating test data 
def item = new Item(name: 'testName') 

def model = controller.deleteItem(item.id) 

item.metaClass.delete = {Map params -> 
    throw new DataIntegrityViolationException('Some error message') 
} 

assertEquals controller.flash.message, "Sorry an error occurred when deleting!!" 

Edit 1 Hinweis Ich habe vergessen, die 'Karte params ->' enthalten im metaclass Schließung. (Wird möglicherweise nicht in allen Versionen von Grails benötigt, da diese Methoden in den verschiedenen Versionen kompiliert werden)