From f18dbaf6e0a9eba144a1d315dee7497b93689f6f Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Thu, 9 Jun 2022 11:19:51 -0400 Subject: [PATCH 1/4] tests(depinject): add preference feature --- depinject/features/prefer.feature | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 depinject/features/prefer.feature diff --git a/depinject/features/prefer.feature b/depinject/features/prefer.feature new file mode 100644 index 000000000000..ee1f2a44f634 --- /dev/null +++ b/depinject/features/prefer.feature @@ -0,0 +1,29 @@ +Feature: interface type resolution + + Background: + Given an interface Duck + And two implementations Mallard and Canvasback + + Rule: interface types can be resolved to a concrete type implicitly if there is only one matching implementation + provided in the container + Scenario: only one implementation + Given "Mallard" is provided + When we try to resolve a "Duck" in global scope + Then "Mallard" is resolved + + Scenario: two implementations + Given "Mallard" and "Canvasback" are provided + When we try to resolve a "Duck" + Then there is an "multiple implicit interface bindings" error + + Scenario: two module-scoped preferences and a global preference + Given "Mallard" and "Canvasback" are provided + * there is a global preference for "Mallard" + * there is a preference for "Canvasback" in module "A" + * there is a preference for "Mallard" in module "B" + When module "A" wants a "Duck" + * module "B" wants a "Duck" + * module "C" wants a "Duck" + Then module "A" resolves a "Canvasback" + * module "B" resolves a "Mallard" + * module "C" resolves a "Mallard" From e8bf79cdfa85ffc8cb48756a18c13af12e5b6dea Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Thu, 9 Jun 2022 11:35:42 -0400 Subject: [PATCH 2/4] add features --- depinject/features/prefer.feature | 86 +++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 17 deletions(-) diff --git a/depinject/features/prefer.feature b/depinject/features/prefer.feature index ee1f2a44f634..862481be78d0 100644 --- a/depinject/features/prefer.feature +++ b/depinject/features/prefer.feature @@ -4,26 +4,78 @@ Feature: interface type resolution Given an interface Duck And two implementations Mallard and Canvasback - Rule: interface types can be resolved to a concrete type implicitly if there is only one matching implementation + Rule: interface types resolve to a concrete type implicitly if there is only one matching implementation provided in the container - Scenario: only one implementation + Example: only one implementation Given "Mallard" is provided When we try to resolve a "Duck" in global scope Then "Mallard" is resolved - Scenario: two implementations + Example: two implementations Given "Mallard" and "Canvasback" are provided - When we try to resolve a "Duck" - Then there is an "multiple implicit interface bindings" error - - Scenario: two module-scoped preferences and a global preference - Given "Mallard" and "Canvasback" are provided - * there is a global preference for "Mallard" - * there is a preference for "Canvasback" in module "A" - * there is a preference for "Mallard" in module "B" - When module "A" wants a "Duck" - * module "B" wants a "Duck" - * module "C" wants a "Duck" - Then module "A" resolves a "Canvasback" - * module "B" resolves a "Mallard" - * module "C" resolves a "Mallard" + When we try to resolve a "Duck" in global scope + Then there is a "multiple implicit interface bindings" error + + Rule: preferences must point to a real type + Example: + Given "Mallard" is provided + And there is a global preference for a "Marbled" "Duck" + When we try to resolve a "Duck" in global scope + Then there is a "no type for explicit binding" error + + Rule: preferences supersede implicit type resolution + Example: global scope + Given "Canvasback" is provided + And there is a global preference for a "Mallard" "Duck" + When we try to resolve a "Duck" in global scope + Then there is a "can't resolve" error + + Example: module scope + Given "Canvasback" is provided + And there is a preference for a "Mallard" "Duck" in module "A" + When module "A" wants a "Duck" + Then there is a "can't resolve" error + + Rule: preferences in global scope apply to both global and module-scoped resolution, if there is no module-scoped preference + Example: global resolution + Given "Mallard" and "Canvasback" are provided + And there is a global preference for a "Mallard" "Duck" + When we try to resolve a "Duck" in global scope + Then "Mallard" is resolved + + Example: module-scoped resolution + Given "Mallard" and "Canvasback" are provided + And there is a global preference for a "Mallard" "Duck" + When module "A" wants a "Duck" + Then module "A" resolves a "Mallard" + + Rule: module-scoped preferences only apply to module-scoped resolution + Example: a module-scoped binding doesn't work for global scope + Given "Mallard" and "Canvasback" are provided + And there is a preference for a "Canvasback" "Duck" in module "A" + When we try to resolve a "Duck" in global scope + Then there is a "multiple implicit interface bindings" error + + Example: a module-scoped binding works for that module + Given "Mallard" and "Canvasback" are provided + And there is a preference for a "Canvasback" "Duck" in module "A" + When module "A" wants a "Duck" + Then module "A" resolves a "Canvasback" + + Example: a module-scoped binding doesn't work for another module + Given "Mallard" and "Canvasback" are provided + And there is a preference for a "Canvasback" "Duck" in module "A" + When module "B" wants a "Duck" + Then there is a "multiple implicit interface bindings" error + + Example: two module-scoped preferences and a global preference + Given "Mallard" and "Canvasback" are provided + * there is a global preference for a "Mallard" "Duck" + * there is a preference for a "Canvasback" "Duck" in module "A" + * there is a preference for a "Mallard" "Duck" in module "B" + When module "A" wants a "Duck" + * module "B" wants a "Duck" + * module "C" wants a "Duck" + Then module "A" resolves a "Canvasback" + * module "B" resolves a "Mallard" + * module "C" resolves a "Mallard" From 767b431617e873cc7fc5c6cb6fc62695d99472c3 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Thu, 9 Jun 2022 11:43:37 -0400 Subject: [PATCH 3/4] updates --- depinject/features/prefer.feature | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/depinject/features/prefer.feature b/depinject/features/prefer.feature index 862481be78d0..ce5cddd20740 100644 --- a/depinject/features/prefer.feature +++ b/depinject/features/prefer.feature @@ -5,11 +5,10 @@ Feature: interface type resolution And two implementations Mallard and Canvasback Rule: interface types resolve to a concrete type implicitly if there is only one matching implementation - provided in the container Example: only one implementation Given "Mallard" is provided When we try to resolve a "Duck" in global scope - Then "Mallard" is resolved + Then "Mallard" is resolved in global scope Example: two implementations Given "Mallard" and "Canvasback" are provided @@ -36,12 +35,12 @@ Feature: interface type resolution When module "A" wants a "Duck" Then there is a "can't resolve" error - Rule: preferences in global scope apply to both global and module-scoped resolution, if there is no module-scoped preference + Rule: preferences in global scope apply to both global and module-scoped resolution (if there is no module-scoped preference) Example: global resolution Given "Mallard" and "Canvasback" are provided And there is a global preference for a "Mallard" "Duck" When we try to resolve a "Duck" in global scope - Then "Mallard" is resolved + Then "Mallard" is resolved in global scope Example: module-scoped resolution Given "Mallard" and "Canvasback" are provided @@ -79,3 +78,4 @@ Feature: interface type resolution Then module "A" resolves a "Canvasback" * module "B" resolves a "Mallard" * module "C" resolves a "Mallard" + * "Mallard" is resolved in global scope From 858d998422585d686690ec897a737b2a50d740b0 Mon Sep 17 00:00:00 2001 From: Aaron Craelius Date: Thu, 9 Jun 2022 11:46:09 -0400 Subject: [PATCH 4/4] updates --- depinject/features/prefer.feature | 3 +++ 1 file changed, 3 insertions(+) diff --git a/depinject/features/prefer.feature b/depinject/features/prefer.feature index ce5cddd20740..54a8680c2928 100644 --- a/depinject/features/prefer.feature +++ b/depinject/features/prefer.feature @@ -67,6 +67,9 @@ Feature: interface type resolution When module "B" wants a "Duck" Then there is a "multiple implicit interface bindings" error + # this case is called a "journey" scenario which tests a bunch of things together + # most tests should be short and to the point like the ones above but one or two long ones + # are good to test more things together &/or do integration tests Example: two module-scoped preferences and a global preference Given "Mallard" and "Canvasback" are provided * there is a global preference for a "Mallard" "Duck"