1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//! 契约测试模块
//!
//! 提供基于 Pact 的契约测试工具,支持消费者和提供者的契约定义与验证。
#[cfg(feature = "pact")]
pub use pact_impl::*;
#[cfg(feature = "pact")]
mod pact_impl {
use pact_consumer::prelude::*;
use pact_verifier::*;
use std::path::PathBuf;
/// 消费者契约构建器
///
/// 用于定义消费者与提供者之间的契约。
pub struct ConsumerPactBuilder {
pact: PactBuilder,
}
impl ConsumerPactBuilder {
/// 创建新的消费者契约构建器
///
/// # 参数
/// - `consumer_name`: 消费者名称
/// - `provider_name`: 提供者名称
pub fn new(consumer_name: &str, provider_name: &str) -> Self {
let pact = PactBuilder::new(consumer_name, provider_name);
Self { pact }
}
/// 创建新的 V4 版本的消费者契约构建器
///
/// # 参数
/// - `consumer_name`: 消费者名称
/// - `provider_name`: 提供者名称
pub fn new_v4(consumer_name: &str, provider_name: &str) -> Self {
let pact = PactBuilder::new_v4(consumer_name, provider_name);
Self { pact }
}
/// 添加 HTTP 交互
///
/// # 参数
/// - `description`: 交互描述
/// - `test_name`: 测试名称(可选)
/// - `f`: 构建交互的闭包
pub fn interaction<F>(mut self, description: &str, test_name: &str, f: F) -> Self
where
F: FnOnce(RequestResponsePactInteraction) -> RequestResponsePactInteraction,
{
self.pact = self.pact.interaction(description, test_name, f);
self
}
/// 开始 Mock 服务器
///
/// # 参数
/// - `addr`: 监听地址(可选)
/// - `tls`: TLS 配置(可选)
pub fn start_mock_server(
self,
addr: Option<std::net::SocketAddr>,
tls: Option<pact_consumer::mock_server::TlsConfig>,
) -> pact_consumer::mock_server::MockServer {
self.pact.start_mock_server(addr, tls)
}
/// 异步开始 Mock 服务器
///
/// # 参数
/// - `addr`: 监听地址(可选)
/// - `tls`: TLS 配置(可选)
pub async fn start_mock_server_async(
self,
addr: Option<std::net::SocketAddr>,
tls: Option<pact_consumer::mock_server::TlsConfig>,
) -> pact_consumer::mock_server::MockServer {
self.pact.start_mock_server_async(addr, tls).await
}
}
/// 提供者验证配置
///
/// 用于配置提供者契约验证的参数。
pub struct ProviderVerifier {
provider_info: ProviderInfo,
pact_sources: Vec<PactSource>,
verification_options: VerificationOptions,
}
impl ProviderVerifier {
/// 创建新的提供者验证器
///
/// # 参数
/// - `provider_name`: 提供者名称
/// - `host`: 提供者主机地址
/// - `port`: 提供者端口
pub fn new(provider_name: &str, host: &str, port: u16) -> Self {
let provider_info = ProviderInfo {
name: provider_name.to_string(),
protocol: "http".to_string(),
host: host.to_string(),
port: Some(port),
path: "/".to_string(),
};
Self { provider_info, pact_sources: Vec::new(), verification_options: VerificationOptions::default() }
}
/// 设置协议
///
/// # 参数
/// - `protocol`: 协议(http 或 https)
pub fn protocol(mut self, protocol: &str) -> Self {
self.provider_info.protocol = protocol.to_string();
self
}
/// 设置路径
///
/// # 参数
/// - `path`: 基础路径
pub fn path(mut self, path: &str) -> Self {
self.provider_info.path = path.to_string();
self
}
/// 添加契约源为文件
///
/// # 参数
/// - `file`: 契约文件路径
pub fn pact_file(mut self, file: &str) -> Self {
self.pact_sources.push(PactSource::File(PathBuf::from(file)));
self
}
/// 添加契约源为文件目录
///
/// # 参数
/// - `dir`: 契约文件目录路径
pub fn pact_directory(mut self, dir: &str) -> Self {
self.pact_sources.push(PactSource::FileDirectory(PathBuf::from(dir)));
self
}
/// 添加契约源为 Pact Broker
///
/// # 参数
/// - `broker_url`: Pact Broker 地址
/// - `consumer_name`: 消费者名称(可选)
pub fn pact_broker(mut self, broker_url: &str, consumer_name: Option<&str>) -> Self {
self.pact_sources.push(PactSource::BrokerUrl {
url: broker_url.to_string(),
auth: None,
consumer_name: consumer_name.map(|s| s.to_string()),
provider_name: Some(self.provider_info.name.clone()),
});
self
}
/// 设置验证选项
///
/// # 参数
/// - `options`: 验证选项
pub fn verification_options(mut self, options: VerificationOptions) -> Self {
self.verification_options = options;
self
}
/// 同步执行提供者验证
pub fn verify(self) -> Result<(), Box<dyn std::error::Error>> {
verify_provider(self.provider_info, self.pact_sources, None, None, self.verification_options)?;
Ok(())
}
/// 异步执行提供者验证
pub async fn verify_async(self) -> Result<(), Box<dyn std::error::Error>> {
verify_provider_async(self.provider_info, self.pact_sources, None, None, self.verification_options).await?;
Ok(())
}
}
}