首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用嵌套生成器编写jqwik生成器方法

如何使用嵌套生成器编写jqwik生成器方法
EN

Stack Overflow用户
提问于 2019-10-23 05:55:54
回答 2查看 462关注 0票数 2

使用jqwik.net,尝试生成一个内部嵌套了RuleConfig类的规则类。RuleConfig类有一个嵌套的ruleProps,它是一个地图

statusReturnedFromApplyingRule方法总是返回一个初始化的规则,而不是使用@provide方法值??返回规则:rule:Rule{ruleId='null', inputMetricSelector=null, ruleConfig='RuleConfig{ruleType='null', ruleProps={}}'}, elements:[{}]

下面是我的代码:

代码语言:javascript
复制
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);
    }
}

提亚

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-10-23 14:42:34

您正在基于错误的假设构建generateRule方法,该假设认为任意函数的map方法在被调用时会执行任何实际操作。事实并非如此。map返回另一个任意实例的事实给出了一个强烈的提示。

您必须掌握的基本思想是,提供程序方法-用@Provide注释的方法-只不过是生成过程的“描述”;它只会被调用一次。实际的对象生成是在之后发生的,并由框架控制。

下面是一个修改过的generateRule方法,它应该能完成您想要做的事情:

代码语言:javascript
复制
@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;
    });
}

你可以看到的是,创建一个生成器就像数据流编程一样:从一些基本的任意器开始-- lowThresholdArbhighThresholdArb --你组合、映射和过滤它们。最后,必须返回Arbitrary的单个实例。

顺便说一下:如果您希望每次需要Rule时都应用此生成器,则可以编写以下类:

代码语言:javascript
复制
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
        ...
    }
}

register it as a default provider

票数 1
EN

Stack Overflow用户

发布于 2019-10-23 23:32:53

以上地图的其他示例基于提供的答案:

代码语言:javascript
复制
    @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;
    });
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58512811

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档