2014-11-18 2 views
1

Я хочу протестировать контроллер Grails, который содержит bean-компонент (я переведу его в Сервис, когда я его заработаю, но я просто хочу сохранить его простым сейчас).Как инициализировать/проводные бобы в Grails Spock unit tests?

//resources.groovy 
beans { 
    myBean(com.me.MyBean) 
} 


// MyBean.java 
// this needs to be in java as it is playing with spring-data-neo4j 
package com.me; 
public class MyBean { 
    String show() { 
     return "Hello"; 
    } 
} 

// TestController.groovy 
package com.me 

import com.me.MyBean 

class TestController { 

    def myBean 

    def index() { 
     render myBean.show() 
    } 
} 


// TestControllerSpec.groovy 
package com.me 

import grails.test.mixin.TestFor 
import spock.lang.Specification 

import com.me.* 

@TestFor(TestController) 
class TestControllerSpec extends Specification { 

    def myBean 

    def setup() { 
     defineBeans { 
      myBean(com.me.MyBean) {bean-> 
       bean.autowire = true 
      } 
     } 
    } 

    def cleanup() { 
    } 

    def "show() returns Hello"() { 
     when: 
     def rc = controller.myBean.show() 
     def rc2 = myBean.show() 

     then: 
     rc == "Hello" 
     rc2 == "Hello" 
    } 
} 

В пределах TestControllerSpec myBean имеет значение null. controller.myBean также имеет значение null. Я думаю, это связано с тем, что Spring не собирает компонент и не подключает его. Я понимаю, что в модульных тестах не все весенние бобы доступны, но что мне нужно сделать, чтобы получить контроллер.myBean, чтобы он был создан и правильно подключен?

+0

Возможно, вы не захотите это делать в модульных тестах. Вы можете издеваться над ним или заглушить его в методе 'setup':' def setup() {controller.myBean = Stub (MyBean)} ', а затем использовать [взаимодействия] (http://spock-framework.readthedocs.org/en /latest/interaction_based_testing.html), чтобы проверить ваш контроллер. –

+0

Согласовано, но то, что show() на самом деле делает в моем реальном коде, записывает в базу данных графа, которая хранится в памяти. Я хочу проверить, что мой метод фактически приводит к тому, что реальные данные записываются в db, а не в том, что мой метод вызывает метод, который записывает в db (т. Е. Путем насмешивания). (И, конечно, в процессе, чтобы лучше понять, как работает Spring). – John

+2

Но не было бы лучше написать единичный тест для MyBean и выполнить там этот тест? В противном случае интеграция или функциональный шаг могут иметь больший смысл в этом случае. –

ответ

3

Вы должны быть насмешливым myBean ниже

def myBean = Mock(MyBean) 

или

MyBean myBean = Mock() 

, а затем гасите метод для вашей потребности, если требуются, как показано ниже:

myBean.show >> "test data" 

, а затем назначить это объект контроллера, который уже издевается над вами.

controller.myBean = myBean 

и там вы идете.

Или, возможно, вы можете заглушить myBean и дать прореживаемые реализации. Например,

MyBean myBean = Stub(){ 
show() >> {return "sample text"} 
} 
controller.myBean = myBean 

Причина этого в том, что мы не тестировании интеграции прикладных объектов, как контроллеры, или домен, но мы протестируем одну единицу т.е. метода и, следовательно, мы должны просто испытывать его и для интеграции мы должны использовать тестовые примеры интеграции, которые были бы похожи во всем, за исключением того, что вы не будете требовать никакого издевательств в нормальных сценариях.

Edit:

нашел другую полезную функцию издеваться услуг или бобов с использованием defineBeans закрытия, как показано ниже:

 defineBeans { 
      adapter(Adapter) 
      helperService(HelperService) 
     } 

Это позволит фасолью быть доступны из grailsApplication.

Надеюсь, это поможет.