diff --git a/CHANGELOG.md b/CHANGELOG.md index d31a288..6e06786 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,13 @@ -# 1.1.0 (2019-05-05) +# 1.1.1 (2019-06-02) + +## Features +* **Single/SingleOrDefault:** Methods implementated as composite supported methods (Where and Take(2)). + +## Bug Fixes +* **Queries:** Implicit bools in nested methods. ([#PR41](https://github.com/matteobortolazzo/couchdb-net/pull/41)) +* **FxCopAnalyzers:** Removed from NuGet dependencies. + +# 1.1.0 (2019-05-05) ## Features * **_find:** IQueryable methods that are not supported by CouchDB are evaluated in-memory using the IEnumerable counterpart, if possible. diff --git a/LATEST_CHANGE.md b/LATEST_CHANGE.md index 2128c8f..11a21fc 100644 --- a/LATEST_CHANGE.md +++ b/LATEST_CHANGE.md @@ -1,2 +1,6 @@ ## Features -* **_find:** IQueryable methods that are not supported by CouchDB are evaluated in-memory using the IEnumerable counterpart, if possible. +* **Single/SingleOrDefault:** Methods implementated as composite supported methods (Where and Take(2)). + +## Bug Fixes +* **Queries:** Implicit bools in nested methods. ([#PR41](https://github.com/matteobortolazzo/couchdb-net/pull/41)) +* **FxCopAnalyzers:** Removed from NuGet dependencies. diff --git a/README.md b/README.md index 9e82e0e..8d646cc 100644 --- a/README.md +++ b/README.md @@ -181,16 +181,21 @@ If the Where method is not called in the expression, it will at an empty selecto ### Composite methods -Some methods that are not directly supported by CouchDB are converted to a composition of supported ones. +Some methods that are not directly supported by CouchDB are converted to a composition of supported ones, +and the in-memory LINQ method will be executed at the end. | Input | Output | |:----------------------------------|:--------------------------------------| | Min(r => r.Age) | OrderBy(r => r.Age).Take(1) | | Max(r => r.Age) | OrderByDescending(r => r.Age).Take(1) | -| Single() | Take(1) | -| SingleOrDefault() | Take(1) | -| Single(r => r.Age == 19) | Where(r => r.Age == 19).Take(1) | -| SingleOrDefault(r => r.Age == 19) | Where(r => r.Age == 19).Take(1) | +| First() | Take(1) | +| FirstOrDefault() | Take(1) | +| First(r => r.Age == 19) | Where(r => r.Age == 19).Take(1) | +| FirstOrDefault(r => r.Age == 19) | Where(r => r.Age == 19).Take(1) | +| Single() | Take(2) | +| SingleOrDefault() | Take(2) | +| Single(r => r.Age == 19) | Where(r => r.Age == 19).Take(2) | +| SingleOrDefault(r => r.Age == 19) | Where(r => r.Age == 19).Take(2) | **WARN**: Do not call a method twice, for example: `Where(func).Single(func)` won't work. diff --git a/src/CouchDB.Driver/CouchDB.Driver.csproj b/src/CouchDB.Driver/CouchDB.Driver.csproj index d674d4d..0ba647a 100644 --- a/src/CouchDB.Driver/CouchDB.Driver.csproj +++ b/src/CouchDB.Driver/CouchDB.Driver.csproj @@ -7,7 +7,7 @@ false A .NET Standard driver for CouchDB. https://github.com/matteobortolazzo/couchdb-net - https://github.com/matteobortolazzo/couchdb-ne + https://github.com/matteobortolazzo/couchdb-net couchdb,driver,nosql,netstandard,pouchdb,xamarin http://couchdb.apache.org/image/couch@2x.png @@ -26,7 +26,7 @@ - + diff --git a/src/CouchDB.Driver/CouchQueryProvider.cs b/src/CouchDB.Driver/CouchQueryProvider.cs index 910fa96..68730ca 100644 --- a/src/CouchDB.Driver/CouchQueryProvider.cs +++ b/src/CouchDB.Driver/CouchQueryProvider.cs @@ -163,8 +163,19 @@ MethodInfo FindEnumerableMethod() Type[] genericParameters = queryableMethodInfo.GetGenericArguments(); Type[] usableParameters = genericParameters.Take(requestedGenericParameters.Length).ToArray(); MethodInfo enumarableGenericMethod = enumarableMethodInfo.MakeGenericMethod(usableParameters); - var filtered = enumarableGenericMethod.Invoke(null, invokeParameter.ToArray()); - return filtered; + try + { + var filtered = enumarableGenericMethod.Invoke(null, invokeParameter.ToArray()); + return filtered; + } + catch (TargetInvocationException e) + { + if (e.InnerException != null) + { + throw e.InnerException; + } + throw; + } } private object GetArgumentValueFromExpression(Expression e) diff --git a/src/CouchDB.Driver/ExpressionVisitors/BoolMemberToConstantEvaluator.cs b/src/CouchDB.Driver/ExpressionVisitors/BoolMemberToConstantEvaluator.cs index 6714356..435efce 100644 --- a/src/CouchDB.Driver/ExpressionVisitors/BoolMemberToConstantEvaluator.cs +++ b/src/CouchDB.Driver/ExpressionVisitors/BoolMemberToConstantEvaluator.cs @@ -4,25 +4,31 @@ namespace CouchDB.Driver.CompositeExpressionsEvaluator { - internal class BoolMemberToConstantEvaluator : ExpressionVisitor + internal class BoolMemberToConstantEvaluator : ExpressionVisitor { - private bool _visitingWhereMethod; + private bool _isVisitingWhereMethodOrChild; protected override Expression VisitMethodCall(MethodCallExpression m) { - _visitingWhereMethod = m.Method.Name == nameof(Queryable.Where) && m.Method.DeclaringType == typeof(Queryable); - if (_visitingWhereMethod) + bool isRootWhereMethod = !_isVisitingWhereMethodOrChild && m.Method.Name == nameof(Queryable.Where) && m.Method.DeclaringType == typeof(Queryable); + if (isRootWhereMethod) { - Expression result = base.VisitMethodCall(m); - _visitingWhereMethod = false; - return result; + _isVisitingWhereMethodOrChild = true; } - return base.VisitMethodCall(m); + + Expression result = base.VisitMethodCall(m); + + if (isRootWhereMethod) + { + _isVisitingWhereMethodOrChild = false; + } + + return result; } protected override Expression VisitBinary(BinaryExpression expression) { - if (_visitingWhereMethod && expression.Right is ConstantExpression c && c.Type == typeof(bool) && + if (_isVisitingWhereMethodOrChild && expression.Right is ConstantExpression c && c.Type == typeof(bool) && (expression.NodeType == ExpressionType.Equal || expression.NodeType == ExpressionType.NotEqual)) { return expression; @@ -50,8 +56,8 @@ protected override Expression VisitUnary(UnaryExpression expression) private bool IsWhereBooleanExpression(MemberExpression expression) { - return _visitingWhereMethod && - expression.Member is PropertyInfo info && + return _isVisitingWhereMethodOrChild && + expression.Member is PropertyInfo info && info.PropertyType == typeof(bool); } } diff --git a/src/CouchDB.Driver/ExpressionVisitors/CompositeExpressionsEvaluator.cs b/src/CouchDB.Driver/ExpressionVisitors/CompositeExpressionsEvaluator.cs index 73db91b..b90931a 100644 --- a/src/CouchDB.Driver/ExpressionVisitors/CompositeExpressionsEvaluator.cs +++ b/src/CouchDB.Driver/ExpressionVisitors/CompositeExpressionsEvaluator.cs @@ -12,9 +12,9 @@ protected override Expression VisitMethodCall(MethodCallExpression node) var numberOfParameters = node.Method.GetParameters().Length; // Return an expression representing Queryable.Take(1) - MethodCallExpression GetTakeOneExpression(Expression previousExpression) + MethodCallExpression GetTakeOneExpression(Expression previousExpression, int numberOfElements = 1) { - return Expression.Call(typeof(Queryable), nameof(Queryable.Take), genericArgs.Take(1).ToArray(), previousExpression, Expression.Constant(1)); + return Expression.Call(typeof(Queryable), nameof(Queryable.Take), genericArgs.Take(1).ToArray(), previousExpression, Expression.Constant(numberOfElements)); } // Min(e => e.P) == OrderBy(e => e.P).Take(1) + Min @@ -29,7 +29,7 @@ MethodCallExpression GetTakeOneExpression(Expression previousExpression) MethodCallExpression orderBy = Expression.Call(typeof(Queryable), nameof(Queryable.OrderByDescending), genericArgs, node.Arguments[0], node.Arguments[1]); return GetTakeOneExpression(orderBy); } - // Single and SingleOrDefault have the same behaviour + // First and FirstOrDefault have the same behaviour if (node.Method.Name == nameof(Queryable.First) || node.Method.Name == nameof(Queryable.FirstOrDefault)) { // First() == Take(1) + First @@ -44,6 +44,21 @@ MethodCallExpression GetTakeOneExpression(Expression previousExpression) return GetTakeOneExpression(whereExpression); } } + // Single and SingleOrDefault have the same behaviour + if (node.Method.Name == nameof(Queryable.Single) || node.Method.Name == nameof(Queryable.SingleOrDefault)) + { + // Single() == Take(2) + Single + if (numberOfParameters == 1) + { + return GetTakeOneExpression(node.Arguments[0], 2); + } + // SingleOrDefault(e => e.P) == Where(e => e.P).Take(2) + Single + else if (numberOfParameters == 2) + { + MethodCallExpression whereExpression = Expression.Call(typeof(Queryable), nameof(Queryable.Where), genericArgs, node.Arguments[0], node.Arguments[1]); + return GetTakeOneExpression(whereExpression, 2); + } + } return base.VisitMethodCall(node); } } diff --git a/tests/CouchDB.Driver.E2ETests/Client_Tests.cs b/tests/CouchDB.Driver.E2ETests/Client_Tests.cs index 9ccb091..9977720 100644 --- a/tests/CouchDB.Driver.E2ETests/Client_Tests.cs +++ b/tests/CouchDB.Driver.E2ETests/Client_Tests.cs @@ -8,6 +8,7 @@ namespace CouchDB.Driver.E2E { + [Trait("Category", "Integration")] public class ClientTests { [Fact] @@ -54,10 +55,10 @@ public async Task Users() { users = await client.CreateDatabaseAsync().ConfigureAwait(false); } - + var luke = await users.CreateAsync(new CouchUser(name: "luke", password: "lasersword")).ConfigureAwait(false); Assert.Equal("luke", luke.Name); - + luke = await users.FindAsync(luke.Id).ConfigureAwait(false); Assert.Equal("luke", luke.Name); diff --git a/tests/CouchDB.Driver.UnitTests/Authentication_Test.cs b/tests/CouchDB.Driver.UnitTests/Authentication_Test.cs index a115c98..bc87a5a 100644 --- a/tests/CouchDB.Driver.UnitTests/Authentication_Test.cs +++ b/tests/CouchDB.Driver.UnitTests/Authentication_Test.cs @@ -16,7 +16,7 @@ public async Task None() { using (var httpTest = new HttpTest()) { - // ToList + // ToListAssert httpTest.RespondWithJson(new { Docs = new List() }); // Logout httpTest.RespondWithJson(new { ok = true }); diff --git a/tests/CouchDB.Driver.UnitTests/Find/Find_Selector.cs b/tests/CouchDB.Driver.UnitTests/Find/Find_Selector.cs index 5d1cde2..c916c1d 100644 --- a/tests/CouchDB.Driver.UnitTests/Find/Find_Selector.cs +++ b/tests/CouchDB.Driver.UnitTests/Find/Find_Selector.cs @@ -8,24 +8,24 @@ namespace CouchDB.Driver.UnitTests.Find { public class Find_Selector { - private readonly CouchDatabase rebels; + private readonly CouchDatabase _rebels; public Find_Selector() { var client = new CouchClient("http://localhost"); - rebels = client.GetDatabase(); + _rebels = client.GetDatabase(); } [Fact] public void ToList_EmptySelector() { - var json = rebels.ToString(); + var json = _rebels.ToString(); Assert.Equal(@"{""selector"":{}}", json); } [Fact] public void ComplexQuery() { - var json = rebels.Where(r => + var json = _rebels.Where(r => r.Age == 19 && (r.Name == "Luke" || r.Name == "Leia") && r.Skills.Contains("force")).ToString(); @@ -35,21 +35,21 @@ public void ComplexQuery() public void Variable_Const() { var age = 19; - var json = rebels.Where(r => r.Age == age).ToString(); + var json = _rebels.Where(r => r.Age == age).ToString(); Assert.Equal(@"{""selector"":{""age"":19}}", json); } [Fact] public void Variable_Object() { var luke = new Rebel { Age = 19 }; - var json = rebels.Where(r => r.Age == luke.Age).ToString(); + var json = _rebels.Where(r => r.Age == luke.Age).ToString(); Assert.Equal(@"{""selector"":{""age"":19}}", json); } [Fact] public void ExpressionVariable_Const() { Expression> filter = r => r.Age == 19; - var json = rebels.Where(filter).ToString(); + var json = _rebels.Where(filter).ToString(); Assert.Equal(@"{""selector"":{""age"":19}}", json); } [Fact] @@ -57,13 +57,13 @@ public void ExpressionVariable_Object() { var luke = new Rebel { Age = 19 }; Expression> filter = r => r.Age == luke.Age; - var json = rebels.Where(filter).ToString(); + var json = _rebels.Where(filter).ToString(); Assert.Equal(@"{""selector"":{""age"":19}}", json); } [Fact] public void Enum() { - var json = rebels.Where(r => r.Species == Species.Human).ToString(); + var json = _rebels.Where(r => r.Species == Species.Human).ToString(); Assert.Equal(@"{""selector"":{""species"":0}}", json); } [Fact] @@ -71,43 +71,43 @@ public void GuidQuery() { var guidString = "83c79283-f634-41e3-8aab-674bdbae3413"; var guid = Guid.Parse(guidString); - var json = rebels.Where(r => r.Guid == guid).ToString(); + var json = _rebels.Where(r => r.Guid == guid).ToString(); Assert.Equal(@"{""selector"":{""guid"":""83c79283-f634-41e3-8aab-674bdbae3413""}}", json); } [Fact] public void Variable_Bool_True() { - var json = rebels.Where(r => r.IsJedi).OrderBy(r => r.IsJedi).ToString(); + var json = _rebels.Where(r => r.IsJedi).OrderBy(r => r.IsJedi).ToString(); Assert.Equal(@"{""selector"":{""isJedi"":true},""sort"":[""isJedi""]}", json); } [Fact] public void Variable_Bool_False() { - var json = rebels.Where(r => !r.IsJedi).OrderBy(r => r.IsJedi).ToString(); + var json = _rebels.Where(r => !r.IsJedi).OrderBy(r => r.IsJedi).ToString(); Assert.Equal(@"{""selector"":{""isJedi"":false},""sort"":[""isJedi""]}", json); } [Fact] public void Variable_Bool_ExplicitTrue() { - var json = rebels.Where(r => r.IsJedi == true).OrderBy(r => r.IsJedi).ToString(); + var json = _rebels.Where(r => r.IsJedi == true).OrderBy(r => r.IsJedi).ToString(); Assert.Equal(@"{""selector"":{""isJedi"":true},""sort"":[""isJedi""]}", json); } [Fact] public void Variable_Bool_ExplicitFalse() { - var json = rebels.Where(r => r.IsJedi == false).OrderBy(r => r.IsJedi).ToString(); + var json = _rebels.Where(r => r.IsJedi == false).OrderBy(r => r.IsJedi).ToString(); Assert.Equal(@"{""selector"":{""isJedi"":false},""sort"":[""isJedi""]}", json); } [Fact] public void Variable_Bool_ExplicitNotTrue() { - var json = rebels.Where(r => r.IsJedi != true).OrderBy(r => r.IsJedi).ToString(); + var json = _rebels.Where(r => r.IsJedi != true).OrderBy(r => r.IsJedi).ToString(); Assert.Equal(@"{""selector"":{""isJedi"":{""$ne"":true}},""sort"":[""isJedi""]}", json); } [Fact] public void Variable_Bool_ExplicitNotFalse() { - var json = rebels.Where(r => r.IsJedi != false).OrderBy(r => r.IsJedi).ToString(); + var json = _rebels.Where(r => r.IsJedi != false).OrderBy(r => r.IsJedi).ToString(); Assert.Equal(@"{""selector"":{""isJedi"":{""$ne"":false}},""sort"":[""isJedi""]}", json); } } diff --git a/tests/CouchDB.Driver.UnitTests/Find/Find_Selector_Combinations.cs b/tests/CouchDB.Driver.UnitTests/Find/Find_Selector_Combinations.cs index 0dc5086..feab854 100644 --- a/tests/CouchDB.Driver.UnitTests/Find/Find_Selector_Combinations.cs +++ b/tests/CouchDB.Driver.UnitTests/Find/Find_Selector_Combinations.cs @@ -59,10 +59,40 @@ public void ElemMatch() Assert.Equal(@"{""selector"":{""battles"":{""$elemMatch"":{""planet"":""Naboo""}}}}", json); } [Fact] + public void ElemMatchImplicitBool() + { + var json = _rebels.Where(r => r.Battles.Any(b => b.DidWin)).ToString(); + Assert.Equal(@"{""selector"":{""battles"":{""$elemMatch"":{""didWin"":true}}}}", json); + } + [Fact] + public void ElemMatchBoolExplicit() + { + var json = _rebels.Where(r => r.Battles.Any(b => b.DidWin == true)).ToString(); + Assert.Equal(@"{""selector"":{""battles"":{""$elemMatch"":{""didWin"":true}}}}", json); + } + [Fact] + public void ElemMatchNested() + { + var json = _rebels.Where(r => r.Battles.Any(b => b.Vehicles.Any(v => v.CanFly == true))).ToString(); + Assert.Equal(@"{""selector"":{""battles"":{""$elemMatch"":{""vehicles"":{""$elemMatch"":{""canFly"":true}}}}}}", json); + } + [Fact] + public void ElemMatchNestedImplicitBool() + { + var json = _rebels.Where(r => r.Battles.Any(b => b.Vehicles.Any(v => v.CanFly))).ToString(); + Assert.Equal(@"{""selector"":{""battles"":{""$elemMatch"":{""vehicles"":{""$elemMatch"":{""canFly"":true}}}}}}", json); + } + [Fact] public void AllMatch() { var json = _rebels.Where(r => r.Battles.All(b => b.Planet == "Naboo")).ToString(); Assert.Equal(@"{""selector"":{""battles"":{""$allMatch"":{""planet"":""Naboo""}}}}", json); } + [Fact] + public void AllMatchImplicitBool() + { + var json = _rebels.Where(r => r.Battles.All(b => b.DidWin)).ToString(); + Assert.Equal(@"{""selector"":{""battles"":{""$allMatch"":{""didWin"":true}}}}", json); + } } } diff --git a/tests/CouchDB.Driver.UnitTests/SupportByCombination_Tests.cs b/tests/CouchDB.Driver.UnitTests/SupportByCombination_Tests.cs index f01156b..77ea916 100644 --- a/tests/CouchDB.Driver.UnitTests/SupportByCombination_Tests.cs +++ b/tests/CouchDB.Driver.UnitTests/SupportByCombination_Tests.cs @@ -14,7 +14,7 @@ public class SupportByCombination_Tests private readonly CouchDatabase _rebels; private readonly Rebel _mainRebel; private readonly List _rebelsList; - private object _response; + private readonly object _response; public SupportByCombination_Tests() { @@ -38,7 +38,7 @@ public SupportByCombination_Tests() } [Fact] - public async Task Max() + public void Max() { using (var httpTest = new HttpTest()) { @@ -49,7 +49,7 @@ public async Task Max() } [Fact] - public async Task Min() + public void Min() { using (var httpTest = new HttpTest()) { @@ -60,7 +60,7 @@ public async Task Min() } [Fact] - public async Task First() + public void First() { using (var httpTest = new HttpTest()) { @@ -71,7 +71,7 @@ public async Task First() } [Fact] - public async Task First_Expr() + public void First_Expr() { using (var httpTest = new HttpTest()) { @@ -82,7 +82,7 @@ public async Task First_Expr() } [Fact] - public async Task FirstOrDefault() + public void FirstOrDefault() { using (var httpTest = new HttpTest()) { @@ -93,7 +93,7 @@ public async Task FirstOrDefault() } [Fact] - public async Task FirstOrDefault_Expr() + public void FirstOrDefault_Expr() { using (var httpTest = new HttpTest()) { @@ -102,5 +102,67 @@ public async Task FirstOrDefault_Expr() Assert.Null(result); } } + + [Fact] + public void Single() + { + using (var httpTest = new HttpTest()) + { + httpTest.RespondWithJson(_response); + var result = _rebels.AsQueryable().Single(); + Assert.Equal(_mainRebel.Age, result.Age); + } + } + + [Fact] + public void Single_Exception() + { + using (var httpTest = new HttpTest()) + { + httpTest.RespondWithJson(_response); + var result = _rebels.AsQueryable().Single(); + Assert.Equal(_mainRebel.Age, result.Age); + } + } + + [Fact] + public void Single_Expr() + { + using (var httpTest = new HttpTest()) + { + httpTest.RespondWithJson(new + { + Docs = new List + { + new Rebel(), + new Rebel() + } + }); + var ex = Assert.Throws(() => _rebels.AsQueryable().Single()); + Assert.Equal("Sequence contains more than one element", ex.Message); + } + } + + [Fact] + public void SingleOrDefault() + { + using (var httpTest = new HttpTest()) + { + httpTest.RespondWithJson(new { Docs = Array.Empty() }); + var result = _rebels.AsQueryable().SingleOrDefault(); + Assert.Null(result); + } + } + + [Fact] + public void SingleOrDefault_Expr() + { + using (var httpTest = new HttpTest()) + { + httpTest.RespondWithJson(new { Docs = Array.Empty() }); + var result = _rebels.AsQueryable().SingleOrDefault(r => r.Age == 20); + Assert.Null(result); + } + } } } diff --git a/tests/CouchDB.Driver.UnitTests/UnsupportedMethods_Tests.cs b/tests/CouchDB.Driver.UnitTests/UnsupportedMethods_Tests.cs index ca65da2..b773a41 100644 --- a/tests/CouchDB.Driver.UnitTests/UnsupportedMethods_Tests.cs +++ b/tests/CouchDB.Driver.UnitTests/UnsupportedMethods_Tests.cs @@ -13,7 +13,7 @@ public class UnsupportedMethods_Tests private readonly CouchDatabase _rebels; private readonly Rebel _mainRebel; private readonly List _rebelsList; - private object _response; + private readonly object _response; public UnsupportedMethods_Tests() { @@ -37,7 +37,7 @@ public UnsupportedMethods_Tests() } [Fact] - public async Task All() + public void All() { using (var httpTest = new HttpTest()) { @@ -47,7 +47,7 @@ public async Task All() } } [Fact] - public async Task Any() + public void Any() { using (var httpTest = new HttpTest()) { @@ -57,7 +57,7 @@ public async Task Any() } } [Fact] - public async Task Any_Selector() + public void Any_Selector() { using (var httpTest = new HttpTest()) { @@ -68,7 +68,7 @@ public async Task Any_Selector() } [Fact] - public async Task Avg_Expr() + public void Avg_Expr() { using (var httpTest = new HttpTest()) { @@ -79,7 +79,7 @@ public async Task Avg_Expr() } [Fact] - public async Task Count() + public void Count() { using (var httpTest = new HttpTest()) { @@ -90,7 +90,7 @@ public async Task Count() } [Fact] - public async Task CountExpr() + public void CountExpr() { using (var httpTest = new HttpTest()) { @@ -101,7 +101,7 @@ public async Task CountExpr() } [Fact] - public async Task DefaultIfEmpty() + public void DefaultIfEmpty() { using (var httpTest = new HttpTest()) { @@ -112,7 +112,7 @@ public async Task DefaultIfEmpty() } [Fact] - public async Task ElementAt() + public void ElementAt() { using (var httpTest = new HttpTest()) { @@ -122,7 +122,7 @@ public async Task ElementAt() } } [Fact] - public async Task ElementAtOrDefault() + public void ElementAtOrDefault() { using (var httpTest = new HttpTest()) { @@ -133,18 +133,18 @@ public async Task ElementAtOrDefault() } [Fact] - public async Task GroupBy() + public void GroupBy() { using (var httpTest = new HttpTest()) { httpTest.RespondWithJson(_response); var result = _rebels.AsQueryable().GroupBy(c => c.Id); - Assert.Equal(1, result.Count()); + Assert.Single(result); } } [Fact] - public async Task Last() + public void Last() { using (var httpTest = new HttpTest()) { @@ -154,7 +154,7 @@ public async Task Last() } } [Fact] - public async Task Last_Expr() + public void Last_Expr() { using (var httpTest = new HttpTest()) { @@ -165,7 +165,7 @@ public async Task Last_Expr() } [Fact] - public async Task LongCount() + public void LongCount() { using (var httpTest = new HttpTest()) { @@ -176,7 +176,7 @@ public async Task LongCount() } [Fact] - public async Task Reverse() + public void Reverse() { using (var httpTest = new HttpTest()) { @@ -187,7 +187,7 @@ public async Task Reverse() } [Fact] - public async Task SelectMany() + public void SelectMany() { using (var httpTest = new HttpTest()) { @@ -198,7 +198,7 @@ public async Task SelectMany() } [Fact] - public async Task Sum() + public void Sum() { using (var httpTest = new HttpTest()) { diff --git a/tests/CouchDB.Driver.UnitTests/_Models/Battle.cs b/tests/CouchDB.Driver.UnitTests/_Models/Battle.cs index 2e0717c..dcccc17 100644 --- a/tests/CouchDB.Driver.UnitTests/_Models/Battle.cs +++ b/tests/CouchDB.Driver.UnitTests/_Models/Battle.cs @@ -6,7 +6,9 @@ namespace CouchDB.Driver.UnitTests.Models { public class Battle { + public bool DidWin { get; set; } public string Planet { get; set; } public DateTime Date { get; set; } + public List Vehicles { get; set; } = new List(); } } diff --git a/tests/CouchDB.Driver.UnitTests/_Models/Rebel.cs b/tests/CouchDB.Driver.UnitTests/_Models/Rebel.cs index 7c7160c..ff97273 100644 --- a/tests/CouchDB.Driver.UnitTests/_Models/Rebel.cs +++ b/tests/CouchDB.Driver.UnitTests/_Models/Rebel.cs @@ -24,5 +24,10 @@ public override bool Equals(object obj) } return base.Equals(obj); } + + public override int GetHashCode() + { + return base.GetHashCode(); + } } } diff --git a/tests/CouchDB.Driver.UnitTests/_Models/Vehicle.cs b/tests/CouchDB.Driver.UnitTests/_Models/Vehicle.cs new file mode 100644 index 0000000..76ac4d6 --- /dev/null +++ b/tests/CouchDB.Driver.UnitTests/_Models/Vehicle.cs @@ -0,0 +1,7 @@ +namespace CouchDB.Driver.UnitTests.Models +{ + public class Vehicle + { + public bool CanFly { get; set; } + } +} \ No newline at end of file