Skip to content

Commit 92d067b

Browse files
authored
Add cosmos testing and more coverage for table creation scenario (Azure#25937)
1 parent 7a07b18 commit 92d067b

File tree

9 files changed

+263
-92
lines changed

9 files changed

+263
-92
lines changed

sdk/tables/Microsoft.Azure.WebJobs.Extensions.Tables/src/TableEntityWriter.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ internal virtual async Task ExecuteBatchAndCreateTableIfNotExistsAsync(
164164
// Commit the batch
165165
await _table.SubmitTransactionAsync(partition.Values, cancellationToken).ConfigureAwait(false);
166166
}
167-
catch (RequestFailedException e) when (e.Status == 404 && e.ErrorCode == TableErrorCode.TableNotFound)
167+
catch (RequestFailedException e) when
168+
(e.Status == 404 && (e.ErrorCode == TableErrorCode.TableNotFound || e.ErrorCode == TableErrorCode.ResourceNotFound))
168169
{
169170
exception = e;
170171
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using NUnit.Framework;
7+
using NUnit.Framework.Interfaces;
8+
using NUnit.Framework.Internal;
9+
10+
namespace Microsoft.Azure.WebJobs.Extensions.Tables.Tests
11+
{
12+
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
13+
public class GenericTestCaseAttribute : TestCaseAttribute, ITestBuilder
14+
{
15+
private readonly Type _type;
16+
public GenericTestCaseAttribute(Type type, params object[] arguments) : base(arguments)
17+
{
18+
_type = type;
19+
}
20+
21+
IEnumerable<TestMethod> ITestBuilder.BuildFrom(IMethodInfo method, Test suite)
22+
{
23+
return BuildFrom(method.MakeGenericMethod(_type), suite);
24+
}
25+
}
26+
}

sdk/tables/Microsoft.Azure.WebJobs.Extensions.Tables/tests/Microsoft.Azure.WebJobs.Extensions.Tables.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
<Compile Remove="TableEntityValueBinderTests.cs" />
2323
<Compile Remove="EntityPropertyToTConverterFactoryTests.cs" />
2424
<Compile Remove="TToEntityPropertyConverterFactoryTests.cs" />
25+
26+
<Compile Include="..\..\Azure.Data.Tables\tests\TablesTestEnvironment.cs" />
2527
</ItemGroup>
2628

2729
</Project>
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.Threading.Tasks;
5+
using Azure.Data.Tables;
6+
using Newtonsoft.Json.Linq;
7+
using NUnit.Framework;
8+
9+
namespace Microsoft.Azure.WebJobs.Extensions.Tables.Tests
10+
{
11+
public class TableCreationTests : TablesLiveTestBase
12+
{
13+
public TableCreationTests(bool useCosmos): base(useCosmos, createTable: false)
14+
{
15+
}
16+
17+
[GenericTestCase(typeof(ITableEntity))]
18+
[GenericTestCase(typeof(TableEntity))]
19+
[GenericTestCase(typeof(JObject))]
20+
[GenericTestCase(typeof(StructTableEntity))]
21+
[GenericTestCase(typeof(PocoTableEntity))]
22+
public async Task Table_IfBoundToTypeAndTableIsMissing_DoesNotCreate<T>()
23+
{
24+
// Act
25+
await CallAsync<BindEntity<T>>();
26+
// Assert
27+
Assert.False(await TableExistsAsync(TableName));
28+
}
29+
30+
private class BindEntity<T>
31+
{
32+
public static void Call([Table(TableNameExpression, "PK", "RK")] T entity)
33+
{
34+
Assert.AreEqual(default(T), entity);
35+
}
36+
}
37+
38+
[GenericTestCase(typeof(ITableEntity))]
39+
[GenericTestCase(typeof(TableEntity))]
40+
[GenericTestCase(typeof(JObject))]
41+
[GenericTestCase(typeof(StructTableEntity))]
42+
[GenericTestCase(typeof(PocoTableEntity))]
43+
public async Task Table_IfBoundToCollectorAndTableIsMissing_DoesNotCreate<T>()
44+
{
45+
// Act
46+
await CallAsync<BindCollector<T>>();
47+
// Assert
48+
Assert.False(await TableExistsAsync(TableName));
49+
}
50+
51+
private class BindCollector<T>
52+
{
53+
public static void Call([Table(TableNameExpression)] ICollector<T> entities)
54+
{
55+
Assert.NotNull(entities);
56+
}
57+
}
58+
59+
[GenericTestCase(typeof(ITableEntity))]
60+
[GenericTestCase(typeof(TableEntity))]
61+
[GenericTestCase(typeof(JObject))]
62+
[GenericTestCase(typeof(StructTableEntity))]
63+
[GenericTestCase(typeof(PocoTableEntity))]
64+
public async Task Table_IfBoundToCollectorAndTableIsMissingAndAdds_CreatesTable<T>()
65+
{
66+
// Act
67+
await CallAsync<BindCollectorAndAdd<T>>();
68+
// Assert
69+
var entity = TableClient.GetEntityAsync<TableEntity>(PartitionKey, RowKey);
70+
Assert.AreEqual("test value", entity.Result.Value["Value"]);
71+
}
72+
73+
private class BindCollectorAndAdd<T>
74+
{
75+
public static void Call([Table(TableNameExpression)] ICollector<T> entities)
76+
{
77+
entities.Add(Create<T>());
78+
}
79+
}
80+
81+
[GenericTestCase(typeof(ITableEntity))]
82+
[GenericTestCase(typeof(TableEntity))]
83+
[GenericTestCase(typeof(JObject))]
84+
[GenericTestCase(typeof(PocoTableEntity))]
85+
public async Task Table_IfBoundToOutParameterAndTableIsMissingAndAdds_CreatesTable<T>()
86+
{
87+
// Act
88+
await CallAsync<BindOut<T>>();
89+
// Assert
90+
var entity = TableClient.GetEntityAsync<TableEntity>(PartitionKey, RowKey);
91+
Assert.AreEqual("test value", entity.Result.Value["Value"]);
92+
}
93+
94+
private class BindOut<T>
95+
{
96+
public static void Call([Table(TableNameExpression)] out T entity)
97+
{
98+
entity = Create<T>();
99+
}
100+
}
101+
102+
[GenericTestCase(typeof(ITableEntity))]
103+
[GenericTestCase(typeof(TableEntity))]
104+
[GenericTestCase(typeof(JObject))]
105+
[GenericTestCase(typeof(StructTableEntity))]
106+
[GenericTestCase(typeof(PocoTableEntity))]
107+
public async Task Table_IfBoundToReturnAndTableIsMissingAndAdds_CreatesTable<T>()
108+
{
109+
// Act
110+
await CallAsync<BindReturn<T>>();
111+
// Assert
112+
var entity = TableClient.GetEntityAsync<TableEntity>(PartitionKey, RowKey);
113+
Assert.AreEqual("test value", entity.Result.Value["Value"]);
114+
}
115+
116+
private class BindReturn<T>
117+
{
118+
[return: Table(TableNameExpression)]
119+
public static T Call()
120+
{
121+
return Create<T>();
122+
}
123+
}
124+
125+
[Test]
126+
public async Task Table_IfBoundToTableClient_BindsAndCreatesTable()
127+
{
128+
// Act
129+
TableClient result = (await CallAsync<BindToTableClientProgram>()).Table;
130+
131+
// Assert
132+
Assert.NotNull(result);
133+
Assert.AreEqual(TableName, result.Name);
134+
135+
Assert.True(await TableExistsAsync(TableName).ConfigureAwait(false));
136+
}
137+
138+
private class BindToTableClientProgram
139+
{
140+
public void Run([Table(TableNameExpression)] TableClient table)
141+
{
142+
Table = table;
143+
}
144+
145+
public TableClient Table { get; set; }
146+
}
147+
148+
private static T Create<T>()
149+
{
150+
if (typeof(T) == typeof(TableEntity) || typeof(T) == typeof(ITableEntity))
151+
{
152+
return (T)(object)new TableEntity(PartitionKey, RowKey)
153+
{
154+
["Value"] = "test value"
155+
};
156+
}
157+
if (typeof(T) == typeof(JObject))
158+
{
159+
return (T)(object)new JObject()
160+
{
161+
["RowKey"] = RowKey,
162+
["PartitionKey"] = PartitionKey,
163+
["Value"] = "test value"
164+
};
165+
}
166+
167+
if (typeof(T) == typeof(PocoTableEntity))
168+
{
169+
return (T)(object)new PocoTableEntity()
170+
{
171+
RowKey = RowKey,
172+
PartitionKey = PartitionKey,
173+
Value = "test value"
174+
};
175+
}
176+
177+
if (typeof(T) == typeof(StructTableEntity))
178+
{
179+
return (T)(object)new StructTableEntity()
180+
{
181+
RowKey = RowKey,
182+
PartitionKey = PartitionKey,
183+
Value = "test value"
184+
};
185+
}
186+
187+
Assert.Fail();
188+
return default;
189+
}
190+
191+
private class PocoTableEntity
192+
{
193+
public string RowKey { get; set; }
194+
public string PartitionKey { get; set; }
195+
public string Value { get; set; }
196+
}
197+
198+
private struct StructTableEntity
199+
{
200+
public string RowKey { get; set; }
201+
public string PartitionKey { get; set; }
202+
public string Value { get; set; }
203+
}
204+
}
205+
}

sdk/tables/Microsoft.Azure.WebJobs.Extensions.Tables/tests/TableEntityLiveTests.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

44
using System;
5-
using System.Collections.Generic;
65
using System.Threading.Tasks;
76
using Azure;
87
using Azure.Data.Tables;
@@ -13,6 +12,10 @@ namespace Microsoft.Azure.WebJobs.Extensions.Tables.Tests
1312
{
1413
public class TableEntityLiveTests: TablesLiveTestBase
1514
{
15+
public TableEntityLiveTests(bool useCosmos) : base(useCosmos)
16+
{
17+
}
18+
1619
[Test]
1720
public async Task TableEntity_IfBoundToExistingTableEntity_Binds()
1821
{

sdk/tables/Microsoft.Azure.WebJobs.Extensions.Tables/tests/TableTests.cs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

44
using System;
5-
using System.Collections.Generic;
65
using System.Threading;
76
using System.Threading.Tasks;
87
using Azure.Data.Tables;
@@ -20,6 +19,10 @@ public class TableTests: TablesLiveTestBase
2019
{
2120
private const string PropertyName = "Property";
2221

22+
public TableTests(bool useCosmos) : base(useCosmos)
23+
{
24+
}
25+
2326
[Test]
2427
public async Task Table_IndexingFails()
2528
{
@@ -123,19 +126,6 @@ public void Initialize(ExtensionConfigContext context)
123126
}
124127
}
125128

126-
[Test]
127-
public async Task Table_IfBoundToTableClient_BindsAndCreatesTable()
128-
{
129-
// Act
130-
TableClient result = (await CallAsync<BindToTableClientProgram>()).Table;
131-
132-
// Assert
133-
Assert.NotNull(result);
134-
Assert.AreEqual(TableName, result.Name);
135-
136-
Assert.True(await TableExistsAsync(TableName).ConfigureAwait(false));
137-
}
138-
139129
[Test]
140130
public async Task Table_IfBoundToICollectorJObject_AddInsertsEntity()
141131
{

sdk/tables/Microsoft.Azure.WebJobs.Extensions.Tables/tests/TablesLiveTestBase.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Azure;
1010
using Azure.Core.TestFramework;
1111
using Azure.Data.Tables;
12+
using Azure.Data.Tables.Tests;
1213
using Microsoft.Azure.WebJobs.Host;
1314
using Microsoft.Azure.WebJobs.Host.TestCommon;
1415
using Microsoft.Extensions.Configuration;
@@ -18,8 +19,12 @@
1819

1920
namespace Microsoft.Azure.WebJobs.Extensions.Tables.Tests
2021
{
22+
[TestFixture(true)]
23+
[TestFixture(false)]
2124
public class TablesLiveTestBase : LiveTestBase<TablesTestEnvironment>
2225
{
26+
private readonly bool _useCosmos;
27+
private readonly bool _createTable;
2328
protected const string TableNameExpression = "%Table%";
2429
protected const string PartitionKey = "PK";
2530
protected const string RowKey = "RK";
@@ -28,14 +33,25 @@ public class TablesLiveTestBase : LiveTestBase<TablesTestEnvironment>
2833
protected TableServiceClient ServiceClient;
2934
protected TableClient TableClient;
3035

36+
protected TablesLiveTestBase(bool useCosmos, bool createTable = true)
37+
{
38+
_useCosmos = useCosmos;
39+
_createTable = createTable;
40+
}
41+
3142
[SetUp]
3243
public async Task SetUp()
3344
{
3445
TableName = GetRandomTableName();
3546

36-
ServiceClient = new TableServiceClient(TestEnvironment.StorageConnectionString);
47+
ServiceClient = new TableServiceClient(
48+
_useCosmos ? TestEnvironment.CosmosConnectionString : TestEnvironment.StorageConnectionString);
49+
3750
TableClient = ServiceClient.GetTableClient(TableName);
38-
await TableClient.CreateAsync();
51+
if (_createTable)
52+
{
53+
await TableClient.CreateAsync();
54+
}
3955
}
4056
[TearDown]
4157
public async Task TearDown()
@@ -85,7 +101,7 @@ protected async Task<T> CallAsync<T>(string methodName = null, object arguments
85101
builder.AddInMemoryCollection(new Dictionary<string, string>()
86102
{
87103
{"Table", TableName},
88-
{"AzureWebJobsStorage", TestEnvironment.StorageConnectionString}
104+
{"AzureWebJobsStorage", _useCosmos ? TestEnvironment.CosmosConnectionString : TestEnvironment.StorageConnectionString}
89105
});
90106
});
91107

0 commit comments

Comments
 (0)