使用jqwik.net,尝试生成一个内部嵌套了RuleConfig类的规则类。RuleConfig类有一个嵌套的ruleProps,它是一个地图
statusReturnedFromApplyingRule方法总是返回一个初始化的规则,而不是使用@provide方法值??返回规则:rule:Rule{ruleId='null', inputMetricSelector=null, ruleConfig='RuleConfig{ruleType='null', ruleProps={}}'}, elements:[{}]
下面是我的代码:
public class RangeMatchRuleTest {
@Property
@Report(Reporting.GENERATED)
boolean statusReturnedFromApplyingRule(@ForAll("generateRule") Rule rule,
@ForAll("generateInputMapElements") Iterable<Map<String, Object>> elements) {
RangeMatchRule rangeMatchRule = new RangeMatchRule();
final RuleIF.Status status = rangeMatchRule.applyRule(rule, elements);
return RuleIF.getEnums().contains(status.toString());
}
@Provide
Arbitrary<Rule> generateRule() {
Rule rule = new Rule();
RuleConfig ruleConfig = new RuleConfig();
Map<String, Object> ruleProps = new HashMap<>();
Arbitrary<Double> lowThresholdArb = Arbitraries.doubles()
.between(0.0, 29.0);
lowThresholdArb.allValues().ifPresent(doubleStream -> ruleProps.put(Utils.LOW_THRESHOLD, doubleStream.findFirst().get()));
//lowThresholdArb.map(lowThreshold -> ruleProps.put(Utils.LOW_THRESHOLD, lowThreshold) );
Arbitrary<Double> highThresholdArb = Arbitraries.doubles()
.between(30.0, 50.0);
highThresholdArb.map(highThreshold -> ruleProps.put(Utils.HIGH_THRESHOLD, highThreshold));
ruleConfig.setRuleProps(ruleProps);
rule.setRuleConfig(ruleConfig);
return Arbitraries.create(() -> rule);
}
@Provide
Arbitrary<Iterable<Map<String, Object>>> generateInputMapElements() {
Arbitrary<Double> metricValueArb = Arbitraries.doubles()
.between(0, 50.0);
Map<String, Object> inputMap = new HashMap<>();
metricValueArb.map(metricValue -> inputMap.put(Utils.METRIC_VALUE, metricValue));
List<Map<String, Object>> inputMapLst = new ArrayList<>();
inputMapLst.add(inputMap);
return Arbitraries.create(() -> inputMapLst);
}
}提亚
发布于 2019-10-23 14:42:34
您正在基于错误的假设构建generateRule方法,该假设认为任意函数的map方法在被调用时会执行任何实际操作。事实并非如此。map返回另一个任意实例的事实给出了一个强烈的提示。
您必须掌握的基本思想是,提供程序方法-用@Provide注释的方法-只不过是生成过程的“描述”;它只会被调用一次。实际的对象生成是在之后发生的,并由框架控制。
下面是一个修改过的generateRule方法,它应该能完成您想要做的事情:
@Provide
Arbitrary<Rule> generateRule() {
Arbitrary<Double> lowThresholdArb = Arbitraries.doubles()
.between(0.0, 29.0);
Arbitrary<Double> highThresholdArb = Arbitraries.doubles()
.between(30.0, 50.0);
Arbitrary<RuleConfig> configArb =
Combinators.combine(lowThresholdArb, highThresholdArb)
.as((low, high) -> {
Map<String, Object> ruleProps = new HashMap<>();
ruleProps.put(Utils.LOW_THRESHOLD, low);
ruleProps.put(Utils.HIGH_THRESHOLD, high);
RuleConfig ruleConfig = new RuleConfig();
ruleConfig.setRuleProps(ruleProps);
return ruleConfig;
});
return configArb.map(config -> {
Rule rule = new Rule();
rule.setRuleConfig(config);
return rule;
});
}你可以看到的是,创建一个生成器就像数据流编程一样:从一些基本的任意器开始-- lowThresholdArb和highThresholdArb --你组合、映射和过滤它们。最后,必须返回Arbitrary的单个实例。
顺便说一下:如果您希望每次需要Rule时都应用此生成器,则可以编写以下类:
public class RuleArbitraryProvider implements ArbitraryProvider {
@Override
public boolean canProvideFor(TypeUsage targetType) {
return targetType.isOfType(Rule.class);
}
@Override
public Set<Arbitrary<?>> provideFor(TypeUsage targetType, SubtypeProvider subtypeProvider) {
return Collections.singleton(generateRule());
}
private Arbitrary<Rule> generateRule() {
// Put here the code from above
...
}
}发布于 2019-10-23 23:32:53
以上地图的其他示例基于提供的答案:
@Provide
Arbitrary<Iterable<Map<String, Object>>> generateInputMapElements() {
Arbitrary<Double> metricValueArb = Arbitraries.doubles()
.between(0, 50.0);
Arbitrary<Map<String, Object>> inputMapArb =
metricValueArb.map(metricsValue -> {
Map<String, Object> inputMap = new HashMap<>();
inputMap.put(Utils.METRIC_VALUE, metricsValue);
return inputMap;
});
return inputMapArb.map(inputMap -> {
List<Map<String, Object>> inputMapLst = new ArrayList<>();
inputMapLst.add(inputMap);
return inputMapLst;
});
}https://stackoverflow.com/questions/58512811
复制相似问题