Grails/Groovy — использование нескольких @TestMixin

В Grails у меня есть служба, которую я хочу протестировать. Служба использует эти импорты:

import grails.converters.JSON
import grails.web.JSONBuilder

Я хочу, чтобы служба получала данные и преобразовывала их в JSON:

def tables = DataProfileStats.withCriteria {
        projections {
            distinct("tableName")               
            }
        };

Вспомогательный метод, который я написал для создания JSON:

public String buildNodeString(String nodeText)
{
    def builder = new JSONBuilder();

    JSON result = builder.build {
        hello = "world"
        };

    return result.toString();
}

В модульном тесте я должен добавить @TestMixin(ControllerUnitTestMixin), чтобы загрузился адаптер JSON. Но мне также нужно добавить @TestMixin(DomainClassUnitTestMixin), чтобы я мог издеваться над объектом базы данных.

Любые идеи о том, как иметь несколько @TestMixin, или это проблема дизайна, когда у меня есть импорт grails.web.JSONBuilder в классе обслуживания? В противном случае мне придется использовать библиотеку JAVA/JSON или поместить материал JSON в контроллер.

Вот как я хочу, чтобы тест выглядел так:

@TestMixin(ControllerUnitTestMixin)
@TestMixin(DomainClassUnitTestMixin)
class JsTreeJSONGeneratorServiceTests {

void testSomething() {

    DataProfileStats stats1 = new DataProfileStats();
    stats1.tableName = "table";

    mockDomain(DataProfileStats, stats1);

    JsTreeJSONGeneratorService service = new JsTreeJSONGeneratorService();
    String json = service.buildNodeString();
    assert json != "";

}

}

Я получаю класс @TestMixin(ControllerUnitTestMixin) @TestMixin(DomainClassUnitTestMixin) JsTreeJSONGeneratorServiceTests {

void testSomething() {

    DataProfileStats stats1 = new DataProfileStats();
    stats1.tableName = "table";

    mockDomain(DataProfileStats, stats1);

    JsTreeJSONGeneratorService service = new JsTreeJSONGeneratorService();
    String json = service.buildNodeString();
    assert json != "";

}

}

Я получаю класс @TestMixin(ControllerUnitTestMixin) @TestMixin(DomainClassUnitTestMixin) JsTreeJSONGeneratorServiceTests {

void testSomething() {

    DataProfileStats stats1 = new DataProfileStats();
    stats1.tableName = "table";

    mockDomain(DataProfileStats, stats1);

    JsTreeJSONGeneratorService service = new JsTreeJSONGeneratorService();
    String json = service.buildNodeString();
    assert json != "";

}

}

Я получаю исключение «Невозможно указать повторяющуюся аннотацию для одного и того же члена: grails.test.mixin.TestMixin».

Спасибо


person Scott    schedule 26.10.2011    source источник


Ответы (2)


Нашел!

@TestMixin([GrailsUnitTestMixin, ControllerUnitTestMixin, DomainClassUnitTestMixin])
person Scott    schedule 28.10.2011
comment
Поздравляю с решением. Когда вы сможете, обязательно пометьте свой ответ как «принятый», чтобы другие могли учиться на вашем успехе. Ура~ - person Andrew Kozak; 21.12.2011
comment
Спасибо - это помогло мне (хотя я использовал @Mock()). - person duma; 07.04.2014

Очевидно, это связано с ошибкой Grails. Проблема с смешиванием в ControllerUnitTextMixin заключается в том, что оно также выполняет (и/или потенциально будет выполнять) много логики, не связанной или бесполезной для сервисов, и, по сути, является обходным путем, а не исправлением. Ответ Скотта определенно разреженный и чистый в том смысле, что никаких других изменений не вносится, но, учитывая некоторое отсутствие обратной совместимости с Grails 2.0, я был бы обеспокоен будущими выпусками, которые могут, скажем, принудительно включить логику в метод setUp() который может сломаться для обслуживания.

Итак, для полноты картины я включаю еще один потенциальный обходной путь, взятый непосредственно из JIRA, все заслуги Эллери Крейн:

package util.converters

import org.codehaus.groovy.grails.web.converters.configuration.ConvertersConfigurationHolder
import org.codehaus.groovy.grails.web.converters.configuration.ConverterConfiguration
import org.codehaus.groovy.grails.web.converters.configuration.DefaultConverterConfiguration
import org.codehaus.groovy.grails.web.converters.marshaller.ObjectMarshaller
import org.codehaus.groovy.grails.web.converters.Converter
import org.codehaus.groovy.grails.web.converters.configuration.ChainedConverterConfiguration

class JSON extends grails.converters.JSON{

  public JSON(Object target) {
    super(target)
  }

  @Override
  protected ConverterConfiguration<grails.converters.JSON> initConfig() {    
    ConverterConfiguration config = super.initConfig()
    if(config.getOrderedObjectMarshallers().size() == 0){      
      initDefaultMarshallers()
      config = super.initConfig()
    }
    return config
  }

  private void initDefaultMarshallers(){
    List<ObjectMarshaller<grails.converters.JSON>> marshallers = new ArrayList<ObjectMarshaller<grails.converters.JSON>>();
    marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.ArrayMarshaller());
    marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.ByteArrayMarshaller());
    marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.CollectionMarshaller());
    marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.MapMarshaller());
    marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.EnumMarshaller());
    marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.ProxyUnwrappingMarshaller<grails.converters.JSON>());
    marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.DateMarshaller());
    marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.ToStringBeanMarshaller());

    boolean includeDomainVersion = true;
    marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.DomainClassMarshaller(includeDomainVersion));
    marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.GroovyBeanMarshaller());
    marshallers.add(new org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller());

    DefaultConverterConfiguration<grails.converters.JSON> cfg = new DefaultConverterConfiguration<grails.converters.JSON>(marshallers);
    cfg.setEncoding("UTF-8");
    cfg.setCircularReferenceBehaviour(Converter.CircularReferenceBehaviour.DEFAULT)
    cfg.setPrettyPrint(false);
    ConvertersConfigurationHolder.setDefaultConfiguration(grails.converters.JSON.class, new ChainedConverterConfiguration<grails.converters.JSON>(cfg));
  }
}

тогда

Просто импортируйте util.converters.JSON вместо grails.converters.JSON, и все остальное будет работать без проблем.

person Igor    schedule 15.11.2013