在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) 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) class 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”异常。
由于
答案 0 :(得分:20)
发现它!
@TestMixin([GrailsUnitTestMixin, ControllerUnitTestMixin, DomainClassUnitTestMixin])
答案 1 :(得分:0)
显然,这是由于Grails bug。在ControllerUnitTextMixin
中混合的问题在于,它也会(和/或可能会)对服务无关或无用的许多逻辑,并且本质上是一种解决方法而不是修复。斯科特的答案绝对是稀疏和干净的,没有其他任何变化,但鉴于一些缺乏与Grails 2.0的向后兼容性,我会关注未来的版本,可能会强制逻辑进入setUp()方法这可能会破坏服务。
因此,为了完整起见,我将包括另一个直接从JIRA采取的潜在解决方法,全部归功于Ellery Crane:
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,其他一切都可以无缝地工作。