-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathFunctionTestServer.cs
More file actions
147 lines (130 loc) · 6.61 KB
/
FunctionTestServer.cs
File metadata and controls
147 lines (130 loc) · 6.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright 2020, Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Google.Cloud.Functions.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Net.Http;
namespace Google.Cloud.Functions.Testing
{
/// <summary>
/// A test server to simplify in-memory testing.
/// </summary>
public class FunctionTestServer : IDisposable
{
/// <summary>
/// The underlying <see cref="TestServer"/> hosting the function.
/// </summary>
public TestServer Server { get; }
/// <summary>
/// The host containing the test server.
/// </summary>
public IHost Host { get; }
/// <summary>
/// The function type executed by the server.
/// </summary>
public Type FunctionTarget { get; }
private readonly MemoryLoggerProvider _testLoggerProvider;
/// <summary>
/// Creates a FunctionTestServer for the specified function type.
/// </summary>
/// <param name="functionTarget">The function type to host in the server.</param>
public FunctionTestServer(Type functionTarget) : this(functionTarget, null)
{
}
/// <summary>
/// Creates a FunctionTestServer for the specified function type, with an optional
/// type to inspect for <see cref="FunctionsStartupAttribute"/> attributes.
/// </summary>
/// <param name="functionTarget">The function type to host in the server.</param>
/// <param name="startupAttributeSource">A type to examine for <see cref="FunctionsStartupAttribute"/> attributes to provide further customization.
/// If this is null, or no attributes are specified in the type (or its base class hierarchy) or the assembly it's declared in,
/// the startup classes in the function assembly are used.</param>
public FunctionTestServer(Type functionTarget, Type? startupAttributeSource)
: this(FunctionTestServerBuilder.Create(functionTarget).MaybeUseFunctionsStartupsFromAttributes(startupAttributeSource).BuildHost(), functionTarget)
{
}
internal FunctionTestServer(IHost host, Type functionTarget)
{
Host = host;
Server = host.GetTestServer();
FunctionTarget = functionTarget;
_testLoggerProvider = host.Services.GetRequiredService<MemoryLoggerProvider>();
}
/// <summary>
/// Returns a list of the log entries for the category associated with the function.
/// </summary>
/// <returns>A list of log entries. The returned value may refer to an empty list,
/// but is never null.</returns>
public List<TestLogEntry> GetFunctionLogEntries() => GetLogEntries(FunctionTarget);
/// <summary>
/// Creates an <see cref="HttpClient"/> to make requests to the test server.
/// </summary>
/// <returns>An <see cref="HttpClient"/> that will connect to <see cref="Server"/> by default.</returns>
public HttpClient CreateClient() => Server.CreateClient();
/// <summary>
/// Clears all logs. This does not affect any loggers that have already been created, but causes
/// new loggers to be created for future requests.
/// </summary>
public void ClearLogs() => _testLoggerProvider.Clear();
/// <summary>
/// Returns a list of log entries for the category with the given type's full name. If no logs have been
/// written for the given category, an empty list is returned.
/// </summary>
/// <param name="type">The type whose name is used as a logger category name.</param>
/// <returns>A list of log entries for the given category name.</returns>
public List<TestLogEntry> GetLogEntries(Type type) =>
GetLogEntries(LoggerTypeNameHelper.GetCategoryNameForType(Preconditions.CheckNotNull(type, nameof(type))));
/// <summary>
/// Returns a list of log entries for the given category name. If no logs have been
/// written for the given category, an empty list is returned.
/// </summary>
/// <param name="categoryName">The category name for which to get log entries.</param>
/// <returns>A list of log entries for the given category name.</returns>
public List<TestLogEntry> GetLogEntries(string categoryName) =>
_testLoggerProvider.GetLogEntries(Preconditions.CheckNotNull(categoryName, nameof(categoryName)));
/// <summary>
/// Disposes of the host of the test server.
/// </summary>
public void Dispose() => Host.Dispose();
}
/// <summary>
/// Generic version of <see cref="FunctionTestServer"/>, making it particularly simple to specify as
/// a test fixture.
/// </summary>
/// <typeparam name="TFunction">The function type to host in the server</typeparam>
public class FunctionTestServer<TFunction> : FunctionTestServer
{
/// <summary>
/// Constructs a new instance serving <typeparamref name="TFunction"/>.
/// </summary>
public FunctionTestServer() : this(null)
{
}
// Note: it would be nice to make the constructor below public, but that means it can't be used in an
// xUnit test fixture via constructor dependency injection.
/// <summary>
/// Constructs a new instance serving <typeparamref name="TFunction"/>, with an optional
/// type to inspect for <see cref="FunctionsStartupAttribute"/> attributes.
/// </summary>
/// <param name="startupAttributeSource">A type to examine for <see cref="FunctionsStartupAttribute"/> attributes to provide further customization.
/// If this is null, or no attributes are specified in the type (or its base class hierarchy) or the assembly it's declared in,
/// the usual startup classes for the target function are used.</param>
internal FunctionTestServer(Type? startupAttributeSource) : base(typeof(TFunction), startupAttributeSource)
{
}
}
}