+++
title = "Validation Tests"
weight = 2000
+++
### Validation Tests
Sometimes we want the inputs to be configurable, but we also want to put constraints on those inputs or validate
that the input is valid.
Suppose for the `HitCounter` construct we want to allow the user to specify the `ReadCapacity` on the DynamoDB
table, but we also want to ensure the value is within a reasonable range. We can write a test to make sure
that the validation logic works: pass in invalid values and see what happens.
First, add a `ReadCapacity` property to the `HitCounterProps` struct:
{{}}
type HitCounterProps struct {
// Downstream is the function for which we want to count hits
Downstream awslambda.IFunction
ReadCapacity float64
}
{{}}
Then update the DynamoDB table resource to add the `ReadCapacity` property.
{{}}
table := awsdynamodb.NewTable(this, jsii.String("Hits"), &awsdynamodb.TableProps{
PartitionKey: &awsdynamodb.Attribute{Name: jsii.String("path"), Type: awsdynamodb.AttributeType_STRING},
RemovalPolicy: awscdk.RemovalPolicy_DESTROY,
Encryption: awsdynamodb.TableEncryption_AWS_MANAGED,
ReadCapacity: &props.ReadCapacity,
})
{{}}
Now add a validation which will throw an error if the `ReadCapacity` is not in the allowed range.
{{}}
func NewHitCounter(scope constructs.Construct, id string, props *HitCounterProps) HitCounter {
if props.ReadCapacity < 5 || props.ReadCapacity > 20 {
panic("ReadCapacity must be between 5 and 20")
}
{{}}
Don't forget to pass in the ReadCapacity both in our app where we create a HitCounter, and in our existing tests as well
{{}}
hitcounter := hitcounter.NewHitCounter(stack, "HelloHitCounter", &hitcounter.HitCounterProps{
Downstream: helloHandler,
ReadCapacity: 10,
})
{{}}
Now lets add a test that validates the error is thrown.
```go
func TestCanPassReadCapacity(t *testing.T) {
defer jsii.Close()
defer func() {
if r := recover(); r == nil {
t.Error("Did not throw ReadCapacity error")
}
}()
// GIVEN
stack := awscdk.NewStack(nil, nil, nil)
// WHEN
testFn := awslambda.NewFunction(stack, jsii.String("TestFunction"), &awslambda.FunctionProps{
Code: awslambda.Code_FromAsset(jsii.String("lambda"), nil),
Runtime: awslambda.Runtime_NODEJS_16_X(),
Handler: jsii.String("hello.handler"),
})
hitcounter.NewHitCounter(stack, "MyTestConstruct", &hitcounter.HitCounterProps{
Downstream: testFn,
ReadCapacity: 10,
})
}
```
Run the test.
```bash
$ go test
```
You should see an output like this:
```bash
╰─ go test
--- FAIL: TestCanPassReadCapacity (0.01s)
cdk-workshop_test.go:78: Did not throw ReadCapacity error
FAIL
exit status 1
FAIL cdk-workshop 5.442s
```
Now let's change the value of ReadCapacity to be outside the valid range so that this test can succeed
{{}}
func TestCanPassReadCapacity(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Error("Did not throw ReadCapacity error")
}
}()
// GIVEN
stack := awscdk.NewStack(nil, nil, nil)
// WHEN
testFn := awslambda.NewFunction(stack, jsii.String("TestFunction"), &awslambda.FunctionProps{
Code: awslambda.Code_FromAsset(jsii.String("lambda"), nil),
Runtime: awslambda.Runtime_NODEJS_16_X(),
Handler: jsii.String("hello.handler"),
})
hitcounter.NewHitCounter(stack, "MyTestConstruct", &hitcounter.HitCounterProps{
Downstream: testFn,
ReadCapacity: 21,
})
}
{{}}
Now when we run the test it should succeed
```bash
╰─ go test
PASS
ok cdk-workshop 5.384s
```