Verification v3.7.0
WARNING
⚠️ EXPERIMENTAL FEATURE: The GripMock Embedded SDK is currently experimental. The API is subject to change without notice, and functionality may be modified in future versions. Use at your own risk.
INFO
Minimum Requirements: Go 1.26 or later
Verify that your code interacts with the mock as expected.
Call Verification
go
func TestMyService_CallVerification(t *testing.T) {
// ARRANGE
mock, err := sdk.Run(t, sdk.WithFileDescriptor(service.File_service_proto))
require.NoError(t, err)
mock.Stub("MyService", "MyMethod").
When(sdk.Equals("id", "test")).
Reply(sdk.Data("result", "success")).
Commit()
client := NewMyServiceClient(mock.Conn())
// ACT - Make calls to the mock
_, _ = client.MyMethod(t.Context(), &MyRequest{Id: "test"})
_, _ = client.MyMethod(t.Context(), &MyRequest{Id: "test"})
// ASSERT - Verify the method was called exactly 2 times
mock.Verify().Method("MyService", "MyMethod").Called(t, 2)
}Total Call Verification
go
func TestMyService_TotalCalls(t *testing.T) {
// ARRANGE
mock, err := sdk.Run(t, sdk.WithFileDescriptor(service.File_service_proto))
require.NoError(t, err)
mock.Stub("MyService", "MethodA").
When(sdk.Equals("id", "a")).
Reply(sdk.Data("result", "A")).
Commit()
mock.Stub("MyService", "MethodB").
When(sdk.Equals("id", "b")).
Reply(sdk.Data("result", "B")).
Commit()
client := NewMyServiceClient(mock.Conn())
// ACT - Make calls to different methods
_, _ = client.MethodA(t.Context(), &MethodARequest{Id: "a"})
_, _ = client.MethodB(t.Context(), &MethodBRequest{Id: "b"})
_, _ = client.MethodA(t.Context(), &MethodARequest{Id: "a"})
// ASSERT - Verify total calls to all methods
mock.Verify().Total(t, 3) // 2 calls to MethodA + 1 call to MethodB
}Call History
go
func TestMyService_History(t *testing.T) {
// ARRANGE
mock, err := sdk.Run(t, sdk.WithFileDescriptor(service.File_service_proto))
require.NoError(t, err)
mock.Stub("MyService", "MyMethod").
When(sdk.Equals("id", "tracked")).
Reply(sdk.Data("result", "ok")).
Commit()
client := NewMyServiceClient(mock.Conn())
// ACT - Make some calls
_, _ = client.MyMethod(t.Context(), &MyRequest{Id: "tracked"})
_, _ = client.MyMethod(t.Context(), &MyRequest{Id: "tracked"})
// ASSERT - Check history
calls := mock.History().FilterByMethod("MyService", "MyMethod")
require.Len(t, calls, 2)
// Check the request data
require.Equal(t, "tracked", calls[0].Request["id"])
require.Equal(t, "tracked", calls[1].Request["id"])
// Verify individual calls
mock.Verify().Method("MyService", "MyMethod").Called(t, 2)
}Never Called Verification
go
func TestMyService_NeverCalled(t *testing.T) {
// ARRANGE
mock, err := sdk.Run(t, sdk.WithFileDescriptor(service.File_service_proto))
require.NoError(t, err)
mock.Stub("MyService", "UsedMethod").
When(sdk.Equals("id", "used")).
Reply(sdk.Data("result", "success")).
Commit()
// Don't define stub for UnusedMethod - it shouldn't be called
client := NewMyServiceClient(mock.Conn())
// ACT - Only call the used method
_, _ = client.UsedMethod(t.Context(), &UsedMethodRequest{Id: "used"})
// ASSERT - Verify the unused method was never called
mock.Verify().Method("MyService", "UnusedMethod").Never(t)
// Also verify the used method was called once
mock.Verify().Method("MyService", "UsedMethod").Called(t, 1)
}Automatic Verification with Times
When using the Times feature, the SDK automatically verifies that the expected number of calls were made:
go
func TestMyService_TimesVerification(t *testing.T) {
// ARRANGE
// Pass t to Run to enable automatic verification
mock, err := sdk.Run(t, sdk.WithFileDescriptor(service.File_service_proto))
require.NoError(t, err)
// Stub that should be called exactly 2 times
mock.Stub("MyService", "MyMethod").
When(sdk.Equals("id", "limited")).
Reply(sdk.Data("result", "ok")).
Times(2). // Expected to be called exactly 2 times
Commit()
client := NewMyServiceClient(mock.Conn())
// ACT - Make 2 calls (the exact number specified in Times)
_, _ = client.MyMethod(t.Context(), &MyRequest{Id: "limited"})
_, _ = client.MyMethod(t.Context(), &MyRequest{Id: "limited"})
// ASSERT - When t is passed to Run, verification happens automatically at test cleanup
// If the actual call count doesn't match the Times value, the test will fail
// The test will pass because we made exactly 2 calls as specified in Times(2)
}Complex Verification Scenario
go
func TestOrderService_ComplexVerification(t *testing.T) {
// ARRANGE
mock, err := sdk.Run(t, sdk.WithFileDescriptor(order.File_order_service_proto))
require.NoError(t, err)
// Create stubs with different call limits
mock.Stub("OrderService", "CreateOrder").
When(sdk.Equals("userId", "premium")).
Reply(sdk.Data("orderId", "ORD-001")).
Times(1). // Should be called exactly once
Commit()
mock.Stub("OrderService", "CancelOrder").
When(sdk.Equals("orderId", "ORD-001")).
Reply(sdk.Data("status", "cancelled")).
Times(1). // Should be called exactly once
Commit()
mock.Stub("OrderService", "GetOrder").
When(sdk.Equals("orderId", "ORD-001")).
Reply(sdk.Data("status", "active")).
Times(2). // Should be called exactly twice
Commit()
client := NewOrderServiceClient(mock.Conn())
// ACT
// Create order
createResp, err := client.CreateOrder(t.Context(), &CreateOrderRequest{UserId: "premium"})
require.NoError(t, err)
// Check order status twice
_, err = client.GetOrder(t.Context(), &GetOrderRequest{OrderId: "ORD-001"})
require.NoError(t, err)
_, err = client.GetOrder(t.Context(), &GetOrderRequest{OrderId: "ORD-001"})
require.NoError(t, err)
// Cancel order
_, err = client.CancelOrder(t.Context(), &CancelOrderRequest{OrderId: "ORD-001"})
require.NoError(t, err)
// ASSERT - Verification happens automatically due to Times() and passing t to Run()
// All verifications will pass because we made the exact number of calls specified
require.Equal(t, "ORD-001", createResp.GetOrderId())
}Verification with History Analysis
go
func TestPaymentService_HistoryAnalysis(t *testing.T) {
// ARRANGE
mock, err := sdk.Run(t, sdk.WithFileDescriptor(payment.File_payment_service_proto))
require.NoError(t, err)
mock.Stub("PaymentService", "ProcessPayment").
When(sdk.Equals("amount", 100)).
Reply(sdk.Data("transactionId", "TXN-100")).
Commit()
mock.Stub("PaymentService", "ProcessPayment").
When(sdk.Equals("amount", 200)).
Reply(sdk.Data("transactionId", "TXN-200")).
Commit()
client := NewPaymentServiceClient(mock.Conn())
// ACT
_, _ = client.ProcessPayment(t.Context(), &ProcessPaymentRequest{Amount: 100})
_, _ = client.ProcessPayment(t.Context(), &ProcessPaymentRequest{Amount: 200})
_, _ = client.ProcessPayment(t.Context(), &ProcessPaymentRequest{Amount: 100})
// ASSERT
// Check total calls
mock.Verify().Total(t, 3)
// Check specific method calls
mock.Verify().Method("PaymentService", "ProcessPayment").Called(t, 3)
// Analyze history
allCalls := mock.History().All()
require.Len(t, allCalls, 3)
// Verify specific call details
require.Equal(t, float64(100), allCalls[0].Request["amount"])
require.Equal(t, "TXN-100", allCalls[0].Response["transactionId"])
require.Equal(t, float64(200), allCalls[1].Request["amount"])
require.Equal(t, "TXN-200", allCalls[1].Response["transactionId"])
require.Equal(t, float64(100), allCalls[2].Request["amount"])
require.Equal(t, "TXN-100", allCalls[2].Response["transactionId"])
}WARNING
⚠️ EXPERIMENTAL FEATURE: The GripMock Embedded SDK is currently experimental. The API is subject to change without notice, and functionality may be modified in future versions. Use at your own risk.