Я работаю над модулем тестирования кода, написанного моим боссом. Он рисует пробел, и я новичок в TDD, так что мозговой штурм со мной, пожалуйста.Unit Testing с использованием spock mocking или grails mockFor: Исключение нулевого указателя
Мой файл для проверки, EmailAssist - это вспомогательный класс для службы, не показанной здесь. EmailAssist должен ссылаться на несколько других сервисов, включая sectionService, как показано.
class EmailAssist {
def sectionService
//condensed to relevant items
List<CommonsMultipartFile> attachments
Map emailMap =[:]
User user
Boolean valid
public EmailAssist(){
valid = false
}
public EmailAssist(GrailsParameterMap params, User user){
//irrelevant code here involving snipped items
this.setSections(params.list('sections'))
//series of other similar calls which are also delivering an NPE
}
//third constructor using third parameter, called in example but functionally
//similar to above constructor.
//definition of errant function
void setSections(List sections) {
emailMap.sections = sectionService.getEmailsInSectionList(sections, user)
}
Раздел SectionService, что вызывается следующим образом.
Set<String> getEmailsInSectionList(List<String> sections, User user) {
if(sections && user){
//code to call DB and update list
}
else{
[]
}
Мое тестирование не предоставляет раздел, так что это должно возвращать пустой список, тем более, что я не могу даже получить доступ к БД в тестовом модуле.
Единичный тест следующий. Это использует mockFor, потому что не показалось, что функциональная функция spock - это то, что мне нужно.
@TestMixin(GrailsUnitTestMixin)
class EmailAssistSpec extends Specification {
@Shared
GrailsParameterMap params
@Shared
GrailsMockHttpServletRequest request = new GrailsMockHttpServletRequest()
@Shared
User user
@Shared
def sectionService
def setup() {
user = new User(id: 1, firstName: "1", lastName: "1", username: "1", email: "[email protected]")
def sectionServiceMock = mockFor(SectionService)
sectionServiceMock.demand.getEmailsInSectionList() {
[]
}
sectionService = sectionServiceMock.createMock()
}
def cleanup(){
}
void testGetFiles(){
when:
//bunch of code to populate request
params = newGrailsParameterMap([:], request)
EmailAssist assist = new EmailAssist(params, request, user)
//Above constructor call generates NPE
Точная NPE выглядит следующим образом: java.lang.NullPointerException: Невозможно вызвать метод getEmailsInSectionList() на нулевой объект на
emailMap.sections = sectionService.getEmailsInSectionList(sections, user)
Который есть тело моей функции setSections, для те из вас, кто играет дома. Стек NPE возникает в вызове конструктора в моем тестовом файле. Я также пробовал использовать spock-style mocking, но служба по-прежнему считается нулевой. Худшая часть заключается в том, что конструктор не является тем, что этот тест должен тестировать, он просто отказывается передать это и в результате сделать тесты невозможными для запуска.
Если есть более подробная информация, которую я могу предоставить, чтобы прояснить ситуацию, дайте мне знать, спасибо!
Редактировать: Я коротко замыкал сеттеры в конструкторе для завершения тестов, но это оставляет некоторые очевидные отверстия в покрытии для испытаний, что я не могу понять, как исправить. Может быть, мое издевательство находится не в том месте? Скукающая документация Спока не очень удобна для сложных функций.
Я собираюсь проверить это. Я буквально только что показал, чтобы сказать, что я понял, что это проблема, я посмотрю, смогу ли я заставить это работать и рассказать вам, что я придумал. – mrfixij
Нет NPE, но кажется, что mockSectionService никогда не вызывается. Даже если я откажусь от этого до «1 * _», он скулит о слишком маленьких вызовах. Не уверен, что об этом думать. – mrfixij
Просто проработать чуть ли не неделю спустя: это решение работало в некотором роде. Неясно, какая часть конструктора была перезаписана и, честно говоря, мы отказались от этой реализации из-за придирки в том, как работает metaClass. В частности, метаклассирование значений несовместимо с самим собой. Пример [здесь] (http://stackoverflow.com/questions/27489785/groovy-metaclass-fails-when-overriding-method-called-in-constructor) – mrfixij