MockAgentTransport lets you test agent interactions deterministically without a running LangGraph server. Script exact event sequences, step through streaming lifecycles, and verify every signal transition in your Angular test specs.
✓No flaky tests
MockAgentTransport eliminates network dependencies, timing issues, and server state. Every test run produces identical results. Your CI pipeline stays green.
Before testing the Angular side, make sure your agent logic is correct. LangGraph agents are plain Python functions — test them directly with pytest.
import pytestfrom langchain_core.messages import HumanMessagefrom my_agent.agent import graph@pytest.mark.asyncioasync def test_agent_responds(): result = await graph.ainvoke( {"messages": [HumanMessage(content="Hello")]}, config={"configurable": {"thread_id": "test_1"}}, ) assert len(result["messages"]) >= 2 assert result["messages"][-1].type == "ai"@pytest.mark.asyncioasync def test_agent_uses_tools(): result = await graph.ainvoke( {"messages": [HumanMessage(content="Search for LangGraph docs")]}, config={"configurable": {"thread_id": "test_2"}}, ) # Verify the agent called the search tool tool_messages = [m for m in result["messages"] if m.type == "tool"] assert len(tool_messages) > 0
iAgent tests are fast
With MemorySaver and a mocked LLM, agent tests run in milliseconds. Use langchain_core.language_models.FakeListChatModel to remove the LLM dependency entirely.
On the Angular side, MockAgentTransport replaces the real HTTP transport. Create it inside TestBed.runInInjectionContext so agent() has access to Angular's dependency injection.
Pass event batches to the constructor for sequential playback. Each call to nextBatch() returns one batch; emit that batch to advance what the component sees.
const transport = new MockAgentTransport([ // Batch 1: Agent starts thinking [{ type: 'values', messages: [{ role: 'assistant', content: 'Analyzing...' }] }], // Batch 2: Agent finishes [{ type: 'values', messages: [{ role: 'assistant', content: 'Here is your answer.' }] }],]);TestBed.runInInjectionContext(() => { const chat = agent({ assistantId: 'test_agent', transport, }); chat.submit({ message: 'Explain signals' }); // Step through each batch transport.emit(transport.nextBatch()); expect(chat.messages()[0].content).toBe('Analyzing...'); transport.emit(transport.nextBatch()); expect(chat.messages()[0].content).toBe('Here is your answer.');});
The most common test pattern verifies the full submit-to-idle lifecycle: submit sets the agent running, values arrive, and the status settles back to idle.
Script an interrupt event to test human-in-the-loop flows. Verify the interrupt signal surfaces the payload, then resume and confirm the agent continues.
import { TestBed } from '@angular/core/testing';import { MockAgentTransport, agent } from '@ngaf/langgraph';describe('interrupt handling', () => { it('should surface interrupt and resume on approval', () => { const transport = new MockAgentTransport(); TestBed.runInInjectionContext(() => { const chat = agent({ assistantId: 'approval_agent', transport, }); // Agent hits an interrupt transport.emit([ { type: 'interrupt', value: { action: 'delete_account', risk: 'high' }, }, ]); // Verify interrupt signal expect(chat.interrupt()).toBeDefined(); expect(chat.interrupt()?.value.action).toBe('delete_account'); expect(chat.interrupt()?.value.risk).toBe('high'); // User approves — resume the agent chat.submit({ resume: { approved: true } }); // Agent continues after approval transport.emit([ { type: 'values', messages: [{ role: 'assistant', content: 'Account deleted.' }], }, ]); expect(chat.interrupt()).toBeUndefined(); expect(chat.messages()[0].content).toBe('Account deleted.'); }); });});
For end-to-end confidence, run tests against a real LangGraph dev server. The LangGraph CLI starts a local server that your tests can hit directly.
# Start the dev serverlanggraph dev --config langgraph.json# Run Angular tests against it (no MockAgentTransport needed)ng test --watch=false
!Integration tests are slow
Integration tests hit a real server and (potentially) a real LLM. Reserve them for CI pipelines or pre-release smoke tests. Use MockAgentTransport for the vast majority of your test suite — it runs in milliseconds with zero external dependencies.