Implement IDisposable for derived types for WebApplicationFactory<T> (#7637)

* Implement IDisposable for derived types for WebApplicationFactory<T>

Add a protected Dispose method and a finalizer to WebApplicationFactory<T> for use in classes that derive from it and want to dispose of their own resources.
Resolves #7631.

* Address review feedback

Only dispose of fields if disposing is true.
This commit is contained in:
Martin Costello 2018-04-13 17:30:33 +01:00 committed by Artak
parent e34b4e8335
commit 2e761415e4
1 changed files with 38 additions and 6 deletions

View File

@ -20,6 +20,7 @@ namespace Microsoft.AspNetCore.Mvc.Testing
/// Typically the Startup or Program classes can be used.</typeparam> /// Typically the Startup or Program classes can be used.</typeparam>
public class WebApplicationFactory<TEntryPoint> : IDisposable where TEntryPoint : class public class WebApplicationFactory<TEntryPoint> : IDisposable where TEntryPoint : class
{ {
private bool _disposed;
private TestServer _server; private TestServer _server;
private Action<IWebHostBuilder> _configuration; private Action<IWebHostBuilder> _configuration;
private IList<HttpClient> _clients = new List<HttpClient>(); private IList<HttpClient> _clients = new List<HttpClient>();
@ -54,6 +55,14 @@ namespace Microsoft.AspNetCore.Mvc.Testing
_configuration = ConfigureWebHost; _configuration = ConfigureWebHost;
} }
/// <summary>
/// Finalizes an instance of the <see cref="WebApplicationFactory{TEntryPoint}"/> class.
/// </summary>
~WebApplicationFactory()
{
Dispose(false);
}
/// <summary> /// <summary>
/// Gets the <see cref="TestServer"/> created by this <see cref="WebApplicationFactory{TEntryPoint}"/>. /// Gets the <see cref="TestServer"/> created by this <see cref="WebApplicationFactory{TEntryPoint}"/>.
/// </summary> /// </summary>
@ -327,17 +336,40 @@ namespace Microsoft.AspNetCore.Mvc.Testing
/// <inheritdoc /> /// <inheritdoc />
public void Dispose() public void Dispose()
{ {
foreach (var client in _clients) Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <param name="disposing">
/// <see langword="true" /> to release both managed and unmanaged resources;
/// <see langword="false" /> to release only unmanaged resources.
/// </param>
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{ {
client.Dispose(); return;
} }
foreach (var factory in _derivedFactories) if (disposing)
{ {
factory.Dispose(); foreach (var client in _clients)
{
client.Dispose();
}
foreach (var factory in _derivedFactories)
{
factory.Dispose();
}
_server?.Dispose();
} }
_server?.Dispose(); _disposed = true;
} }
private class DelegatedWebApplicationFactory : WebApplicationFactory<TEntryPoint> private class DelegatedWebApplicationFactory : WebApplicationFactory<TEntryPoint>