https://stackoverflow.com/questions/3459287/whats-the-differ...
Stubs do not react based on their input parameters. However, even fakes have the issue of fault injection.
I don't want to just test valid inputs. I want to make sure I pass the correct inputs for the request parameters through to the dependencies. If pass 100.00 in the request but in my impl I pass 0.00 to the stub. The test will pass because the input is valid. But the implementation is not correct.
Also, mockery is just an alternative mocking api. There is nothing special here.
How would you test the case where the quota update fails with a stub? Here is mockery example again generated with chatgpt.
func TestHandleTransaction_QuotaUpdateFails(t *testing.T) {
// Create the mock services
mockAuth := new(mocks.AuthService)
mockPayment := new(mocks.PaymentService)
mockStorage := new(mocks.StorageService)
mockQuota := new(mocks.QuotaService)
mockNotification := new(mocks.NotificationService)
// Setup expectations
mockAuth.On("Authenticate", mock.Anything).Return("12345", nil)
mockQuota.On("CheckQuota", "12345").Return(true, nil) // Quota check passes
mockQuota.On("UpdateQuota", "12345", mock.AnythingOfType("int64")).Return(errors.New("quota update failed")) // Quota update fails
// No need to mock payment and storage as they should not be called if quota update fails
// Create the server with mock services
server := &Server{
Auth: mockAuth,
Payment: mockPayment,
Storage: mockStorage,
Quota: mockQuota,
Notification: mockNotification,
}
// Create a test request
transaction := TransactionRequest{
UserID: "12345",
AuthToken: "valid-token",
ProductID: "product123",
Price: 100.0,
Currency: "USD",
File: []byte("file data"),
}
requestBody, _ := json.Marshal(transaction)
request := httptest.NewRequest(http.MethodPost, "/transaction", bytes.NewReader(requestBody))
responseRecorder := httptest.NewRecorder()
// Call the endpoint
server.HandleTransaction(responseRecorder, request)
// Check the results
assert.Equal(t, http.StatusInternalServerError, responseRecorder.Code)
response := TransactionResponse{}
json.NewDecoder(responseRecorder.Body).Decode(&response)
assert.Equal(t, "error", response.Status)
assert.Contains(t, response.Message, "quota update failed")
// Assert that all expectations were met
mockAuth.AssertExpectations(t)
mockQuota.AssertExpectations(t)
// Assert no calls to payment and storage
mockPayment.AssertNotCalled(t, "Charge", mock.AnythingOfType("float64"), mock.AnythingOfType("string"), mock.AnythingOfType("string"))
mockStorage.AssertNotCalled(t, "Upload", mock.AnythingOfType("[]uint8"), "bucket-name", "key-name")
// No notification should be sent
mockNotification.AssertNotCalled(t, "SendNotification", "12345", mock.AnythingOfType("string"))
}