小编Eat*_*age的帖子

将 Pact 与生成的客户端 Api 服务结合使用

我目前正在研究 Pact,作为测试策略开发的一部分。它是一个微服务架构,并且有各种服务器到服务器的连接,我可以看到它非常有用(包括消息队列)。

然而,我无法准确理解它应该如何工作的一个地方是客户端和服务器之间的连接。在我们最常见的模式中,我们有一个 Java 微服务,充当 Typescript/Angular Web 客户端的服务器。服务器采用OpenAPI规范;具体来说,我们手动编写 OpenAPI 规范文件,然后从规范文件生成服务器和客户端代码 - 服务器代码是我们期望实现的控制器的一系列接口,客户端代码是服务和模型库客户端可以使用它向服务器发出请求。客户端上的这种模式使 HTTP 请求变得轻而易举,原因如下:

  1. 模型和控制器在规范文件中定义并在客户端和服务器之间共享,这意味着我们静态执行合约,因此我们在运行测试之前就知道合约是否被破坏
  2. 与服务器交互非常简单,因为生成的控制器服务具有易于使用的 API,可以抽象出主机名、路径等详细信息。

一方面,在此设置中使用 Pact 绝对可以带来一些好处:

  1. pact 文件可用于启动存根服务器,然后该存根服务器可用于支持组件测试。
  2. 它使我们更加倾向于消费者驱动的合同方法(这通常是好的,但前提是我们真正从中受益)。

另一方面,我也有一些担忧:

  1. 我们实际上并不需要 Pact 在测试时提供的语法强制,因为我们在编译时就有了。
  2. 遵循 Pact 文档中建立的准则进行的消费者测试本质上会涉及测试生成的服务代码,这感觉……是错误的。不需要测试生成的代码 - 它应该可以正常工作。而且由于我们的合约测试应该反映实际的客户端行为,因此这些测试之一失败的唯一场景(例如,对 API 进行重大更改)将始终与我们实现中的编译时失败同时发生,从而使测试变得不必要。
  3. 即使我们要编写所有测试,也不清楚我们将在提供商方面采取什么行动。我们可以根据 OpenAPI 定义验证该协议,但我很确定在给定我们的设置的情况下,我们不可能失败这样的验证(除非手动修改协议文件,这似乎是一个很大的禁忌)。诚然,我还没有对提供商方面进行太多调查。

坦率地说,仅第一个积极因素就足以让我承诺加入 Pact。消费者驱动的方法使得生成存根的过程变得更加有意义。话虽这么说,负面影响肯定会让我感到厌烦。感觉工作量很大,其中大部分是引入冗余验证机制,这样我们就可以获取单一利益。

我这样做是错误的吗?我是否可以对这种方法进行简单的改变,以获得相同的好处而不引入冗余?或者我只需要接受这就是方式?

编辑:所以我开始研究使用契约生成存根服务器的工具,结果发现它非常缺乏。内置的 pact 服务器存根不支持以编程方式向正在运行的服务器添加模拟,而且我发现将 pact 转换为与其他服务器存根库一起使用的大多数库都非常小,并且维护得不是特别好。这意味着我们可能必须为存根过程构建我们自己的解决方案,这使得 Pact 的吸引力更小=/

microservices openapi pact

5
推荐指数
1
解决办法
688
查看次数

使用 springdoc 处理递归模型

所以我有一个嵌套模型结构,看起来像这样:

public class TagArea {
    private List<TagGroup> groups;
    
    ... constructors, getters, setters, etc.
}


public class TagGroup {
    private String tagName;
    private List<TagGroup> subgroups;
    
    ... constructors, getters, setters, etc.
}
Run Code Online (Sandbox Code Playgroud)

以及返回所述模型的控制器。但是,生成的 swagger.json 的架构部分如下所示:

{ "components": 
  { "schemas": {
    "TaxonomyClientMetadata": {
      "type": "object", "properties": {
        "tagGroups": {"type": "array", "items": {"$ref": "#/components/schemas/TagGroup"}}
      }
    }, 
    "TagGroup": {
      "type": "object", "properties": {
        "tagName": {"type": "string"}
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

整个财产就这样……消失了。我希望该TagGroup对象看起来更像这样:

"TagGroup": {
  "type": "object", "properties": {
    "tagName": {"type": "string"},
    "subgroups": {"type": "array", …
Run Code Online (Sandbox Code Playgroud)

java openapi springdoc

3
推荐指数
1
解决办法
1788
查看次数

使用非静态方法作为具有泛型的枚举属性

我会尽量保持这个简短.我正在尝试做这样的事情:

public enum Fruit {
    APPLE("Apple", appleHelper::doAppleThing),
    ORANGE("Orange", orangeHelper::doOrangeThing);

    private String name;
    private Function<String, List<T>> fruitFunction;

    Fruit(String name, Function<String, List<T>> fruitFunction) {
      this.name = name;
      this.fruitFunction = fruitFunction;
    }

    public String getName() {
      return name;
    }

    public <T> List<T> applyFruitFunction(String someString) {
      return fruitFunction.apply(someString);
    }
}
Run Code Online (Sandbox Code Playgroud)

这样以后,我可以有一个像这样的方法

private <T> List<T> doFruitThing(String someString, Fruit fruit) {
    List<T> transformedFruits = fruit.applyFruitFunction(someString);

    if (transformedFruits.isEmpty()) {
        throw new FruitException("There was no fruit of type " + fruit.getName());
    }

    return transformedFruits;
}
Run Code Online (Sandbox Code Playgroud)

我遇到了两个问题.

  1. doAppleThing而 …

java enums

2
推荐指数
1
解决办法
49
查看次数

标签 统计

java ×2

openapi ×2

enums ×1

microservices ×1

pact ×1

springdoc ×1