Documentation
¶
Overview ¶
Package govytest provides utilities for testing validation rules defined with govy.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AssertError ¶
func AssertError( t testingT, err error, expectedErrors ...ExpectedRuleError, ) bool
AssertError asserts that the given error has:
- type equal to *govy.ValidatorError
- the expected number of govy.RuleError equal to the number of provided ExpectedRuleError
- at least one error which matches each of the provided ExpectedRuleError
ExpectedRuleError and actual error are considered equal if they have the same property name and:
- [ExpectedRuleError.Code] is equal to govy.RuleError.Code
- [ExpectedRuleError.Message] is equal to govy.RuleError.Message
- [ExpectedRuleError.ContainsMessage] is part of govy.RuleError.Message
At least one of the above must be set for ExpectedRuleError and once set, it will need to match the actual error.
If [ExpectedRuleError.IsKeyError] is provided it will be required to match the actual govy.PropertyError.IsKeyError.
If the actual error is of type govy.ValidatorErrors the following two fields are also matched:
- [ExpectedRuleError.ValidatorName] is equal to govy.ValidatorError.Name
- [ExpectedRuleError.ValidatorIndex] is equal to govy.ValidatorError.SliceIndex
In the above case, all ExpectedRuleError are aggregated per matching *govy.ValidatorError and the function runs for every aggregated validator recursively.
It returns true if the error matches the expectations, false otherwise.
Example ¶
Verifying that expected errors were produced by govy.Validator.Validate can be a tedious task. Often times we might only care about govy.ErrorCode and not the message or description of the error. To help in that process, govytest.AssertError can be used to ensure that the expected errors were produced. It accepts multiple govytest.ExpectedRuleError, each being a short and concise representation of the error we're expecting to occur. For more details on how to use govytest.ExpectedRuleError, see its code documentation.
To demonstrate the erroneous output of govytest.AssertError we'll fail the assertion.
teacherValidator := govy.New(
govy.For(func(t Teacher) string { return t.Name }).
WithName("name").
Required().
Rules(
rules.StringNotEmpty(),
rules.OneOf("Jake", "George")),
govy.For(func(t Teacher) University { return t.University }).
WithName("university").
Include(govy.New(
govy.For(func(u University) string { return u.Address }).
WithName("address").
Required(),
)),
)
teacher := Teacher{
Name: "John",
University: University{
Name: "Poznan University of Technology",
Address: "",
},
}
// We're using a mock testing.T to capture the error produced by the assertion.
mt := new(mockTestingT)
err := teacherValidator.WithName("John").Validate(teacher)
govytest.AssertError(mt, err,
govytest.ExpectedRuleError{
PropertyName: "name",
ContainsMessage: "one of",
},
govytest.ExpectedRuleError{
PropertyName: "university.address",
Code: "greater_than",
},
)
// This will print the error produced by the assertion.
fmt.Println(mt.recordedError)
Output: Expected error was not found. EXPECTED: { "propertyName": "university.address", "code": "greater_than" } ACTUAL: [ { "propertyName": "name", "propertyValue": "John", "errors": [ { "error": "must be one of: Jake, George", "code": "one_of", "description": "must be one of: Jake, George" } ] }, { "propertyName": "university.address", "errors": [ { "error": "property is required but was empty", "code": "required" } ] } ]
Example (ValidatorErrors) ¶
govytest.AssertError can handle not only govy.ValidatorError but also a slice of these wrapped into govy.ValidatorErrors.
For instance, govy.ValidatorErrors is returned from govy.Validator.ValidateSlice, you can also choose to construct this slice type yourself. In any case, in order to match govytest.ExpectedRuleError the assertion function needs to first match it with the right govy.ValidatorError.
In order to achieve that you need to set the following fields:
- govytest.ExpectedRuleError.ValidatorName which matches govy.ValidatorError.Name
- govytest.ExpectedRuleError.ValidatorIndex which matches govy.ValidatorError.SliceIndex
You can set them both, but you need to provide at least one of them.
Every govytest.ExpectedRuleError is aggregated per matched govy.ValidatorError and the function runs recursively for every govy.ValidatorError and expected errors pair.
teacherValidator := govy.New(
govy.For(func(t Teacher) string { return t.Name }).
WithName("name").
Required().
Rules(
rules.StringNotEmpty(),
rules.OneOf("Eve", "George")),
govy.For(func(t Teacher) University { return t.University }).
WithName("university").
Include(govy.New(
govy.For(func(u University) string { return u.Address }).
WithName("address").
Required(),
)),
)
teacherEve := Teacher{
Name: "Eve",
University: University{
Name: "Poznan University of Technology",
Address: "",
},
}
teacherJohn := Teacher{
Name: "John",
University: University{
Name: "Poznan University of Technology",
Address: "Some address",
},
}
teachers := []Teacher{teacherEve, teacherJohn}
// We're using a mock testing.T to capture the error produced by the assertion.
mt := new(mockTestingT)
err := teacherValidator.WithNameFunc(func(s Teacher) string { return s.Name }).ValidateSlice(teachers)
govytest.AssertError(mt, err,
govytest.ExpectedRuleError{
PropertyName: "university.address",
Code: "greater_than",
ValidatorName: "Eve",
ValidatorIndex: ptr(0),
},
govytest.ExpectedRuleError{
PropertyName: "name",
ContainsMessage: "one of",
ValidatorName: "John",
ValidatorIndex: ptr(1),
},
)
// This will print the error produced by the assertion.
fmt.Println(mt.recordedError)
Output: Expected error was not found. EXPECTED: { "propertyName": "university.address", "code": "greater_than", "validatorName": "Eve", "validatorIndex": 0 } ACTUAL: [ { "propertyName": "university.address", "errors": [ { "error": "property is required but was empty", "code": "required" } ] } ]
func AssertErrorContains ¶
func AssertErrorContains( t testingT, err error, expectedError ExpectedRuleError, ) bool
AssertErrorContains asserts that the given error has:
- type equal to *govy.ValidatorError
- at least one error which matches the provided ExpectedRuleError
Unlike AssertError, it checks only a single error. The actual error may contain other errors, If you want to match them all, use AssertError.
ExpectedRuleError and actual error are considered equal if they have the same property name and:
- [ExpectedRuleError.Code] is equal to govy.RuleError.Code
- [ExpectedRuleError.Message] is equal to govy.RuleError.Message
- [ExpectedRuleError.ContainsMessage] is part of govy.RuleError.Message
At least one of the above must be set for ExpectedRuleError and once set, it will need to match the actual error.
If [ExpectedRuleError.IsKeyError] is provided it will be required to match the actual govy.PropertyError.IsKeyError.
If the actual error is of type govy.ValidatorErrors the following two fields are also matched:
- [ExpectedRuleError.ValidatorName] is equal to govy.ValidatorError.Name
- [ExpectedRuleError.ValidatorIndex] is equal to govy.ValidatorError.SliceIndex
It returns true if the error matches the expectations, false otherwise.
Example ¶
If you don't want to verify all the errors returned by govy.Validator, but ensure a single, expected error is produced use govytest.AssertErrorContains instead of govytest.AssertError.
To demonstrate the erroneous output of govytest.AssertErrorContains we'll first match the error and then fail the assertion.
teacherValidator := govy.New(
govy.For(func(t Teacher) string { return t.Name }).
WithName("name").
Required().
Rules(
rules.StringNotEmpty(),
rules.OneOf("Jake", "George")),
govy.For(func(t Teacher) University { return t.University }).
WithName("university").
Include(govy.New(
govy.For(func(u University) string { return u.Address }).
WithName("address").
Required(),
)),
)
teacher := Teacher{
Name: "John",
University: University{
Name: "Poznan University of Technology",
Address: "",
},
}
// We're using a mock testing.T to capture the error produced by the assertion.
mt := new(mockTestingT)
// Match the error.
err := teacherValidator.WithName("John").Validate(teacher)
govytest.AssertErrorContains(mt, err, govytest.ExpectedRuleError{
PropertyName: "name",
Code: "one_of",
})
// Fail to match the error.
err = teacherValidator.WithName("John").Validate(teacher)
govytest.AssertErrorContains(mt, err, govytest.ExpectedRuleError{
PropertyName: "university.address",
Code: "greater_than",
})
// This will print the error produced by the assertion.
fmt.Println(mt.recordedError)
Output: Expected error was not found. EXPECTED: { "propertyName": "university.address", "code": "greater_than" } ACTUAL: [ { "propertyName": "name", "propertyValue": "John", "errors": [ { "error": "must be one of: Jake, George", "code": "one_of", "description": "must be one of: Jake, George" } ] }, { "propertyName": "university.address", "errors": [ { "error": "property is required but was empty", "code": "required" } ] } ]
func AssertNoError ¶
AssertNoError asserts that the provided error is nil. If the error is not nil and of type govy.ValidatorError it will try encoding it to JSON and pretty printing the encountered error.
It returns true if the error is nil, false otherwise.
Example ¶
You can use govytest.AssertNoError to ensure no error was produced by govy.Validator.Validate. If an error was produced, it will be printed to the stdout in JSON format.
To demonstrate the erroneous output of govytest.AssertNoError we'll fail the assertion.
teacherValidator := govy.New(
govy.For(func(t Teacher) string { return t.Name }).
WithName("name").
Required().
Rules(
rules.StringNotEmpty(),
rules.OneOf("Jake", "George")),
govy.For(func(t Teacher) University { return t.University }).
WithName("university").
Include(govy.New(
govy.For(func(u University) string { return u.Address }).
WithName("address").
Required(),
)),
)
teacher := Teacher{
Name: "John",
University: University{
Name: "Poznan University of Technology",
Address: "",
},
}
// We're using a mock testing.T to capture the error produced by the assertion.
mt := new(mockTestingT)
err := teacherValidator.WithName("John").Validate(teacher)
govytest.AssertNoError(mt, err)
// This will print the error produced by the assertion.
fmt.Println(mt.recordedError)
Output: Received unexpected error: { "errors": [ { "propertyName": "name", "propertyValue": "John", "errors": [ { "error": "must be one of: Jake, George", "code": "one_of", "description": "must be one of: Jake, George" } ] }, { "propertyName": "university.address", "errors": [ { "error": "property is required but was empty", "code": "required" } ] } ], "name": "John" }
Types ¶
type ExpectedRuleError ¶
type ExpectedRuleError struct {
// Optional. Matched against [govy.PropertyError.PropertyName].
// It should be only left empty if the validated property has no name.
PropertyName string `json:"propertyName"`
// Optional. Matched against [govy.RuleError.Code].
Code govy.ErrorCode `json:"code,omitempty"`
// Optional. Matched against [govy.RuleError.Message].
Message string `json:"message,omitempty"`
// Optional. Matched against [govy.RuleError.Message] (partial).
ContainsMessage string `json:"containsMessage,omitempty"`
// Optional. Matched against [govy.PropertyError.IsKeyError].
IsKeyError bool `json:"isKeyError,omitempty"`
// Optional. Matched against [govy.ValidatorError.Name].
ValidatorName string `json:"validatorName,omitempty"`
// Optional. Matched against [govy.ValidatorError.SliceIndex].
ValidatorIndex *int `json:"validatorIndex,omitempty"`
}
ExpectedRuleError defines the expectations for the asserted error. Its fields are used to find and match an actual govy.RuleError.