2013-02-28 5 views
5

Korzystanie Grails 2.1.0Testowanie kontrolera Grailsa na temat tworzenia twierdzeń o modelu podczas renderowania szablonu?

Wydaje się, że robi to z kontrolera:

render(view: "someView", model: [modelEntry: "hello"]) 

pozwala mi robić to w badanej jednostki dla tego kontrolera:

controller.method() 
assert model.modelEntry == "hello" 

Jednakże, jeśli Zmieniam kontroler, aby to zrobić:

render(template: "someTemplate", model: [modelEntry: "hello"]) 

Teraz model instancja w teście jest pustą tablicą. Zrobiłem sporo poszukiwań i większość rozwiązań wydaje się być dla Grails 1, często z udziałem obiektu modelAndView (którego nie ma w moim teście) lub renderArgs (ditto).

Jedynym rozwiązaniem znalazłem jest ręcznie zmienić poglądy w teście, jak to:

views['_someTemplate.gsp'] = '${modelEntry}' 

a następnie podejmowania twierdzeń o ciąg. Ale ja nie lubię tego rozwiązania, ponieważ:

  1. wymaga testu zna nazwę pliku szablonu
  2. utrudnia badań modelowych wpisów, które nie mają dobrej toString() metody
  3. utrudnia tworzyć wiele asercji dotyczących powiązanych wpisów modelu.

Czy istnieje sposób na bardziej bezpośredni dostęp do wpisów w modelu z przypadku testowego, gdy kontroler renderuje szablon?

+0

'controller.modelAndView.model' nie istnieje? –

+0

@ SérgioMichels prawidłowe, 'controller.modelAndView' ma wartość null. Należy pamiętać, że używa się stylu idiomatycznego Grails 2, gdzie test jest deklarowany jako '@TestFor (WhateverController)', a test niczego nie rozszerza. Nie jestem pewien, czy funkcja modelAndView działa dla Grails 1 lub dlaczego zawsze widzę tę sugestię, ale i tak nie jest w tym typie testu dla Grails 2. – Rod

Odpowiedz

9

Trochę wgryza się w kod metody renderowania (org.codehaus.groovy.grails.web.metaclass.RenderDynamicMethod) Widzę, że modelAndView jest ustawiony tylko podczas renderowania view.

Renderowanie szablonu zwróci wartość null modelAndView.

Aby sprawdzić model w tym przypadku, myślę, że można użyć Groovy metaClass. Chodzi o to, aby przechwycić oryginalną metodę, zapisać wartość, a następnie zadzwonić do niego.

podstawie this question, I zbudował ten (nie testowane, może potrzebować obrazu Regulacja):

@TestFor(MyController) 
class MyControllerTests 

    def templateModel 

    @Test 
    void inspectTemplateModel() { 
    def originalMethod = MyController.metaClass.getMetaMethod('render', [Map] as Class[]) 
    controller.metaClass.render = { Map args -> 
     templateModel = args.model 
     originalMethod.invoke(delegate, args) 
    } 

    controller.method() 
    assert templateModel.modelEntry == 'foo' 

} 
+0

Tak, to działało. Coś niesamowitego, że wymaga tego rodzaju oszustwa. Naprawdę podjąłem twoje rozwiązanie o krok dalej, zamiast szablonu TemplateModel faktycznie przypisuję modelAndView do instancji kontrolera, sprawiając, że reszta kodu działa tak, jakbyś oczekiwał, gdyby był widok. – Rod

+0

Cóż, możesz podnieś [JIRA] (http://jira.grails.org/browse/GRAILS), prosząc o lepszy sposób dostępu do szablonu do testów. To jest piękno poprawy :) –