Add comprehensive MockProvider integration tests

Added 6 new integration tests for stream_completion_with_tools:
- test_text_before_tool_call_preserved: text before native tool call is saved
- test_native_tool_call_execution: native tool calls execute correctly
- test_duplicate_tool_calls_skipped: sequential duplicates are detected
- test_json_fallback_tool_calling: JSON tool calls work without native support
- test_text_after_tool_execution_preserved: follow-up text is saved
- test_multiple_tool_calls_executed: multiple tool calls in sequence work

Also added MockResponse helper methods:
- text_then_native_tool(): text followed by native tool call
- duplicate_native_tool_calls(): same tool call twice (for dedup testing)

Fixed text_with_json_tool() to ensure "tool" key comes before "args"
(serde_json alphabetizes keys, breaking pattern detection).

Total: 18 integration tests covering historical bugs and core behaviors.
This commit is contained in:
Dhanji R. Prasanna
2026-01-19 14:44:30 +05:30
parent 5caa101b84
commit 2043a83e7d
2 changed files with 224 additions and 5 deletions

View File

@@ -159,13 +159,49 @@ impl MockResponse {
}
}
/// Create a response with text followed by a native tool call
pub fn text_then_native_tool(text: &str, tool: &str, args: serde_json::Value) -> Self {
Self {
chunks: vec![
MockChunk::content(text),
MockChunk::tool_streaming(tool),
MockChunk::tool_call(tool, args),
MockChunk::finished("tool_use"),
],
usage: Usage {
prompt_tokens: 100,
completion_tokens: 50 + text.len() as u32 / 4,
total_tokens: 150 + text.len() as u32 / 4,
},
}
}
/// Create a response with duplicate native tool calls (same tool called twice)
/// Used to test duplicate detection
pub fn duplicate_native_tool_calls(tool: &str, args: serde_json::Value) -> Self {
Self {
chunks: vec![
MockChunk::tool_streaming(tool),
MockChunk::tool_call(tool, args.clone()),
// Second identical tool call
MockChunk::tool_streaming(tool),
MockChunk::tool_call(tool, args),
MockChunk::finished("tool_use"),
],
usage: Usage {
prompt_tokens: 100,
completion_tokens: 100,
total_tokens: 200,
},
}
}
/// Create a response with text followed by a JSON tool call (non-native)
pub fn text_with_json_tool(text: &str, tool: &str, args: serde_json::Value) -> Self {
let tool_json = serde_json::json!({
"tool": tool,
"args": args
});
let tool_str = serde_json::to_string(&tool_json).unwrap();
// Manually construct JSON to ensure "tool" comes before "args"
// (serde_json::json! alphabetizes keys, which breaks pattern detection)
let args_str = serde_json::to_string(&args).unwrap();
let tool_str = format!(r#"{{"tool": "{}", "args": {}}}"#, tool, args_str);
let full_content = format!("{}\n\n{}", text, tool_str);
Self {