Mark Ambrazhevich
11/23/2023, 1:08 PMMatt (pactflow.io / pact-js / pact-go)
Matt (pactflow.io / pact-js / pact-go)
Matt (pactflow.io / pact-js / pact-go)
Mark Ambrazhevich
11/24/2023, 10:59 AM_ = pact.VerifyMessageConsumer(t, message, productServiceWrapper)
//cheking only productService, missing compliance with TransformerService and other dependencies
func productServiceWrapper(m dsl.Message) error {
productMessage := *m.Content.(*Product)
productService := NewProductService(mockTransformerService)
err := productService.receiveProductUpdate(productMessage)
if err != nil {
return err
}
return nil
}
//use real transformer and turn it to integration test
func productServiceWrapper(m dsl.Message) error {
productMessage := *m.Content.(*Product)
productService := NewProductService(transformerService)
err := productService.receiveProductUpdate(productMessage)
if err != nil {
return err
}
return nil
}
// bring all the requirements from services here, without calling the service directly
func productServiceWrapper(m dsl.Message) error {
productMessage := *m.Content.(*Product)
// Validate date format (e.g., "2006-01-02")
if _, err := time.Parse("2006-01-02", productMessage.Date); err != nil {
return errors.New("invalid date format")
}
// Check if status is either "active" or "deleted"
if productMessage.Status != "active" && productMessage.Status != "deleted" {
return errors.New("status must be 'active' or 'deleted'")
}
// Additional validations according to services...
return nil
}
Mark Ambrazhevich
11/28/2023, 7:15 AMMatt (pactflow.io / pact-js / pact-go)
NewProductService
and TransformerService
.Matt (pactflow.io / pact-js / pact-go)
Mark Ambrazhevich
12/01/2023, 7:18 AMMatt (pactflow.io / pact-js / pact-go)
Mark Ambrazhevich
12/02/2023, 7:19 AMMatt (pactflow.io / pact-js / pact-go)
Mark Ambrazhevich
12/06/2023, 1:53 PM// Checking only productService
func productServiceWrapper(m dsl.Message) error {
productMessage := *m.Content.(*Product)
productService := NewProductService(mockTransformerService)
err := productService.receiveProductUpdate(productMessage)
if err != nil {
return err
}
return nil
}
func (p *ProductService) receiveProductUpdate(product Product) error {
err := validate(product)
if err != nil {
return err
}
p.transform(product)
p.post(product)
}
func validate(product Product) error {
// Validate date format (e.g., "2006-01-02")
if _, err := time.Parse("2006-01-02", product.Date); err != nil {
return errors.New("invalid date format")
}
// Check if status is either "active" or "deleted"
if product.Status != "active" && product.Status != "deleted" {
return errors.New("status must be 'active' or 'deleted'")
}
// Additional validations according to services...
return nil
}
This approach aims to enhance our consumer tests with additional validation layers, reflecting the downstream business logic requirements. We believe this could keep our test scope narrow while ensuring the tests remain effective and relevant.
What do you think about this approach? Can we go as far as calling only the validate() function in a Pact test instead of the handler, considering it's used in production and maintained by the developers?Matt (pactflow.io / pact-js / pact-go)
receiveProductUpdate
and mock/stub the downstream services, but that would be roughly equivalent anyway. So the answer is probably “yes” from me, with caveats like “as long as you test the other bits”Srinivas Nali
12/10/2023, 9:20 AM// Checking only productService
func productServiceWrapper(m dsl.Message) error {
productMessage := *m.Content.(*Product)
err := validate(productMessage)
if err != nil {
return err
}
return nil
}
so it generates the contract using production requirements code logic, without mocking (option 1) or using the dependency services (option 2).Matt (pactflow.io / pact-js / pact-go)
Srinivas Nali
12/11/2023, 6:08 AM