The exact situation is I'm doing E2E tests with Protractor.NET (.NET port of AngularJS's Protractor E2E framework) and I would like to make some web requests (and the API -- System.Net.Http.HttpClient -- has all Async/Task methods) to Arrange my test before I Act/Assert, only I need to do this same Arrange-ing for several tests.
I'm using xUnit.net as my test runner they use an interface (IUseFixture<T>) for per-fixture setup code. It would be nice if there was a IAsyncUseFixture<T> that had a Task SetFixtureAsync(T t); or something. I don't think such a thing exists. Additionally I don't think constructors can use await either, and constructors are the only other way to execute the same block of code per-test in xUnit.net.
What are my options? .Result? Isn't that bad practice (deadlock)?
xUnit has an IAsyncLifetime interface for async setup/teardown. The methods you need to implement are Task InitializeAsync() and Task DisposeAsync().
InitializeAsync is called immediately after the class has been created, before it is used.
DisposeAsync is called just before IDisposable.Dispose if the class also implements IDisposable.
e.g.
public class MyTestFixture : IAsyncLifetime
{
private string someState;
public async Task InitializeAsync()
{
await Task.Run(() => someState = "Hello");
}
public Task DisposeAsync()
{
return Task.CompletedTask;
}
[Fact]
public void TestFoo()
{
Assert.Equal("Hello", someState);
}
}
I would use AsyncLazy
http://blog.stephencleary.com/2012/08/asynchronous-lazy-initialization.html
In my case I want to run some integration tests against a self hosted web api.
public class BaseTest()
{
private const string baseUrl = "http://mywebsite.web:9999";
private static readonly AsyncLazy<HttpSelfHostServer> server = new AsyncLazy<HttpSelfHostServer>(async () =>
{
try
{
Log.Information("Starting web server");
var config = new HttpSelfHostConfiguration(baseUrl);
new Startup()
.Using(config)
.Add.AttributeRoutes()
.Add.DefaultRoutes()
.Remove.XmlFormatter()
.Serilog()
.Autofac()
.EnsureInitialized();
var server = new HttpSelfHostServer(config);
await server.OpenAsync();
Log.Information("Web server started: {0}", baseUrl);
return server;
}
catch (Exception e)
{
Log.Error(e, "Unable to start web server");
throw;
}
});
public BaseTest()
{
server.Start()
}
}
Related
I am creating a Xamarin Forms application, and I am using the Xamarin Profiler to show that I have a memory leak. I have tracked the memory leak down to where it is happening, but I can't understand WHY it is happening.
I have a class (we will call it MyClass for now). And that class is using a Timer to call a service once every second. That service makes a REST call to retrieve a bunch of information, and then serializes the results back into an object....
MyClass:
public class MyClass : ContentPage
{
private readonly IMyService myService;
public MyClass() : base()
{
}
protected override async void OnAppearing()
{
StartTimer();
}
private void StartTimer()
{
Task.Run(async() =>
{
while(true)
{
myService = ((App)App.Current)
.serviceProvider
.GetRequiredService<IMyService>();
//--- everytime I call myService.GetSystemStatus(), my allocated memory continues to rise
MyResponse response = await myService.GetSystemStatus();
Device.BeginInvokeOnMainThread(() =>
{
// update the UI here...
});
await Task.Delay(1000);
}
});
}
}
MyService (Singleton):
public class MyService : IMyService
{
private readonly IMyHttpClientFactory httpClientFactory;
public MyService(IMyHttpClientFactory httpClientFactory)
{
this.httpClientFactory = httpClientFactory;
}
public async Task<MyResponse> GetSystemStatus()
{
return await httpClientFactory.Create().GetAsync<MyResponse>(
"http://example.com/api/status"
);
}
}
MyHttpClientFactory (Singleton):
public class MyHttpClientFactory : IMyHttpClientFactory
{
private readonly IServiceProvider _serviceProvider;
public MyHttpClientFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public MyHttpClient Create()
{
return _serviceProvider.GetRequiredService<MyHttpClient>();
}
}
MyHttpClient:
public class MyHttpClient : IDisposable
{
private HttpClient _httpClient;
public MyHttpClient ()
{
_httpClient = new HttpClient();
_httpClient.Timeout = TimeSpan.FromSeconds(10);
}
public async Task<T> GetAsync<T>(string url) where T : new()
{
string s = await GetStringAsync(url);
return JsonConvert.DeserializeObject<T>(s);
}
public async Task<string> GetStringAsync(string url)
{
using (var response = await _httpClient.GetAsync(url))
{
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
}
My services are defined as follows:
public partial class App : Application
public ServiceProvider serviceProvider;
public App()
{
IServiceCollection services = new ServiceCollection();
ConfigureServices(services);
serviceProvider = services.BuildServiceProvider();
InitializeComponent();
}
private void ConfigureServices(IServiceCollection services)
{
services.AddHttpClient<MyHttpClient>("MyHttpClient", x =>
{
x.Timeout = TimeSpan.FromSeconds(5);
});
services.AddSingleton<IMyHttpClientFactory, MyHttpClientFactory>();
services.AddSingleton<IMyService, MyService>();
}
}
Best I can tell, the memory is going up because I am referencing the DI MyService inside a separate thread. But I am not sure if this is the reason or if there is something else that would be causing the leak?
Any advice would be greatly appreciated!!!
Thanks!
From what I understand from your code and your comments, it looks like you're looping by calling StartTimer() inside the Device.StartTimer() method.
According to the documentation, Device.StartTimer() is recurring and will occur every X seconds, depending of your interval parameter.
By removing the call to StartTimer() (the one between t.Dispose() and return false of MyClass.StartTimer, your code should work as expected and you will not create a new timer every x seconds
What could be the cause of the leak:
Your MyHttpClient class implements the IDisposable interface, yet the code to use an instance of this class is not leveraging the disposable nature of the object.
Even though the internal HttpClient instance is wrapped in a using statement, the MyHttpClient instance will not be disposed of as you would expect.
// from MyHttpClient class
public async Task<MyResponse> GetSystemStatus()
{
// no using statement here
return await httpClientFactory.Create().GetAsync<MyResponse>(
"http://example.com/api/status"
);
}
// should be:
public async Task<MyResponse> GetSystemStatus()
{
using (var client = await httpClientFactory.Create())
{
return await client.GetAsync<MyResponse>("http://example.com/api/status");
}
}
Another thing to try is to change the location of the resolution of the MyService instance to inside the Task since this is where it is used. This will allow the task to own the resource, and allow it to be collected when the task is complete.
private void StartTimer()
{
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
Task t = Task.Run(async() =>
{
// resolve the service here
myService = ((App)App.Current)
.serviceProvider
.GetRequiredService<IMyService>();
MyResponse response = await myService.GetSystemStatus();
Device.BeginInvokeOnMainThread(() =>
{
// update the UI here...
});
});
t.Wait();
t.Dispose();
StartTimer();
return false;
});
}
A couple of additional observations of your code:
In your HttpClientFactory's Create() method, you are resolving an instance of your client from the DI container.
Your MyHttpClient class has a default constructor which means the resolution is not needed since there are no additional dependencies requiring DI support.
Your code could simply return a new MyHttpClient() instance from the Create() method without the need for DI.
Your MyHttpClient also implements the IMyHttpClient interface, but your factory returns the concrete type. This means you need to either remove the interface as unnecessary or change the return type to be the interface type since the interface is redundant unless it is used.
Thank you all for your answers....
I finally figured out the source of the memory leak.
The problem was that I was referencing "MyService" like this:
myService = ((App)App.Current)
.serviceProvider
.GetRequiredService<IMyService>();
The problem was that the serviceProvider object was a public property on my App. So each time I referenced the provider inside my loop, it was creating the leak.
To get around this, I added an abstract method to each of my pages that implemented MyClass to return the service correctly using DI. This has corrected my memory leak issue....
Thanks all for the help!
I don't think that your timer logic is the cause of the leak.
But in case it is useful to you, here is a clean way to do work periodically, yet if work takes a long time, avoid events "piling up".
Given await/async, no Timer is needed.
(There is an alternative solution that starts/stops a single System.Timers.Timer, but I won't go into that here.)
Replace StartTimer() declaration with the following:
/// <summary> Runs until keepRunning() returns false.
/// Delays by "msecDelay" AFTER finishing the previous loop's non-UI work. </summary>
private void StartTaskLoopWhileKeepRunning(Func<bool> keepRunning, int msecDelay = 250)
{
Task.Run(async () =>
{
while (keepRunning())
{
// Do non-UI work here.
// ... possibly slow work ...
Device.BeginInvokeOnMainThread(() =>
{
// NOTE: This work will run in parallel with the next delay.
// ... Do UI work here. ...
});
// Non-UI thread sleeps for msec.
await Task.Delay(msecDelay);
}
});
}
I'm working with the HostBuilder in .NET Core (not the WebHost !).
I have one Hosted Service running in my application that overrides the ExecuteAsync/StopAsync methods of the background Service and I want to unit test it.
Here is my HostedService:
public class DeviceToCloudMessageHostedService : BackgroundService
{
private readonly IDeviceToCloudMessageService _deviceToCloudMessageService;
private readonly AppConfig _appConfig;
public DeviceToCloudMessageHostedService(IDeviceToCloudMessageService deviceToCloudMessageService, IOptionsMonitor<AppConfig> appConfig)
{
_deviceToCloudMessageService = deviceToCloudMessageService;
_appConfig = appConfig.CurrentValue;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await _deviceToCloudMessageService.DoStuff(stoppingToken);
await Task.Delay(_appConfig.Parameter1, stoppingToken);
}
}
public override Task StopAsync(CancellationToken cancellationToken)
{
Log.Information("Task Cancelled");
_deviceToCloudMessageService.EndStuff();
return base.StopAsync(cancellationToken);
}
I already found this post: Integration Test for Hosted Service in .NET Core
But it's explained for a QueuedBackgroundService and I don't really know if I can test mine the same way.
I just want to know if my code is executed. I don't want any specific result.
Do you have any idea of how I can test it?
You should still be able to follow a similar format as the linked answer.
Mock the dependencies and inject them, invoke the methods under test and assert the expected behavior.
The following uses Moq to mock the dependencies along with ServiceCollection to do the heavy lifting of injecting the dependencies.
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
[TestMethod]
public async Task DeviceToCloudMessageHostedService_Should_DoStuff() {
//Arrange
IServiceCollection services = new ServiceCollection();
services.AddSingleton<IHostedService, DeviceToCloudMessageHostedService>();
//mock the dependencies for injection
services.AddSingleton(Mock.Of<IDeviceToCloudMessageService>(_ =>
_.DoStuff(It.IsAny<CancellationToken>()) == Task.CompletedTask
));
services.AddSingleton(Mock.Of<IOptionsMonitor<AppConfig>>(_ =>
_.CurrentValue == Mock.Of<AppConfig>(c =>
c.Parameter1 == TimeSpan.FromMilliseconds(1000)
)
));
var serviceProvider = services.BuildServiceProvider();
var hostedService = serviceProvider.GetService<IHostedService>();
//Act
await hostedService.StartAsync(CancellationToken.None);
await Task.Delay(1000);//Give some time to invoke the methods under test
await hostedService.StopAsync(CancellationToken.None);
//Assert
var deviceToCloudMessageService = serviceProvider
.GetRequiredService<IDeviceToCloudMessageService>();
//extracting mock to do verifications
var mock = Mock.Get(deviceToCloudMessageService);
//assert expected behavior
mock.Verify(_ => _.DoStuff(It.IsAny<CancellationToken>()), Times.AtLeastOnce);
mock.Verify(_ => _.EndStuff(), Times.AtLeastOnce());
}
Now, ideally this would count as testing framework code since you are basically testing that a BackgroundService behaves as expected when run, but it should demonstrate enough about how one would test such a service in isolation
Another example based on #Nkosi's excellent answer. For I was testing this StartupBackgroundService, which has a protected method ExecuteAsync:
public class StartupBackgroundService : BackgroundService
{
private readonly StartupHealthCheck _healthCheck;
public StartupBackgroundService(StartupHealthCheck healthCheck)
=> _healthCheck = healthCheck;
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
_healthCheck.StartupCompleted = true;
return Task.CompletedTask;
}
}
I can't change the scope from protected to internal and expose it with [assembly: InternalsVisibleTo("TestsAssembly")] because its derived from an Abstract class.
So I came up with this magic, it calls ExecuteAsync not StartAsync:
[Test]
public async Task Should_Setup_StartupBackgroundService()
{
//Arrange
var startUpBackServ = new StartupBackgroundService(new Base.HealthCheck.StartupHealthCheck());
// Act
startUpBackServ.StartAsync(It.IsAny<CancellationToken>()); // It calls ExecuteAsync magically!
//Assert
}
It's MAGIC!
Here's the StartupHealthCheck:
public class StartupHealthCheck : IHealthCheck
{
public bool StartupCompleted { get; set; }
public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context = null, CancellationToken cancellationToken = default)
{
if (StartupCompleted)
{
return Task.FromResult(HealthCheckResult.Healthy("The startup task has completed."));
}
return Task.FromResult(HealthCheckResult.Unhealthy("That startup task is still running."));
}
}
I have a this code
public class ClassToTest
{
private readonly IRepository repository;
public ClassToTest(DI GOES HERE){...}
public DoSomething()
{
Task.Run(async () => {
//some code
repository.ExecuteAsync();
}
}
}
public class Repository : IRepository
{
public Task ExecuteAsync()
{
using (var connection = new SqlConnection(DbConfiguration.DatabaseConnection))
{
return connection.ExecuteAsync(storedProcedure, parameters, commandType: CommandType.StoredProcedure, commandTimeout: Configuration.TransactionTimeout);
}
}
}
[Test]
public void TestMethod()
{
var repository = new Mock<IRepository>;
var classToTest = new ClassToTest();
classToTest.DoSomething();
repository.Veryfy(p => p.ExecuteAsync(), Times.Once());
}
The test fails with this message
Expected invocation on the mock once, but was 0 times: p => p.ExecuteAsync()
Does anyone knows why?
Thanks
As others have alluded, because you're calling Task.Run and not waiting for a response, the Unit test will likely complete before the background task is even started, hence the Moq Verify failure.
Also, your code won't compile as is - when asking a Q on StackOverflow, be sure to give a complete, compilable MVP.
Of special importance is the bug in the code you are trying to test. Repository.ExecuteAsync calls connection.ExecuteAsync, inside a using scope, but this isn't awaited. This will mean that the connection will be disposed before the task completes. You'll need to change the method to async and await the call to defer disposal of the connection.
The wrapper method DoSomething method shouldn't use Task.Run(), although, because it adds no value to the repository Task, it doesn't need to repeat the async / return await, either.
The caller (your Unit test, in this instance) can then await DoSomething (or if the caller genuinely wants to do further processing without awaiting the Task, then leave it to the caller to decide. At least this way, the caller gets a handle to the Task, to check on completion).
The final state of your code might look more like this:
public class ClassToTest
{
private readonly IRepository _repository;
public ClassToTest(IRepository repository)
{
_repository = repository;
}
// Doesn't necessarily need to be async
public Task DoSomething()
{
// We're return the wrapped task directly, and adding no additional value.
return repository.ExecuteAsync();
}
}
public class Repository : IRepository
{
public async Task ExecuteAsync()
{
using (var connection = new SqlConnection(DbConfiguration.DatabaseConnection))
{
// Here we do need to await, otherwise we'll dispose the connection
return await connection.ExecuteAsync(storedProcedure, parameters,
commandType: CommandType.StoredProcedure,
commandTimeout: Configuration.TransactionTimeout);
}
}
}
// NUnit has full support for async / await
[Test]
public async Task TestMethod()
{
var repository = new Mock<IRepository>();
var classToTest = new ClassToTest(repository.Object);
repository.Setup(_ => _.ExecuteAsync()).Returns(Task.FromResult((object)null));
// Moq also has support for async, e.g. .ReturnsAsync
// You need to await the test.
await classToTest.DoSomething();
repository.Verify(p => p.ExecuteAsync(), Times.Once());
}
I'm using service remoting to connect service A with service B. While deploying, I've noticed that it is possible for service A to call a method in service B while service B is still starting up. In which case AddStringToDictionary throws a NullReferenceException because RunAsync has not been called yet.
public interface IServiceB : IService
{
Task AddStringToDictionary(string key, string value);
}
internal sealed class ServiceB : StatefulService, IServiceB
{
private IReliableDictionary<string, string> myDictionary;
public ServiceB(StatefulServiceContext context)
: base(context)
{
// StateMananger is null here.
}
public async Task AddStringToDictionary(string key, string value)
{
using (var tx = StateManager.CreateTransaction())
{
// myDictionary is null if this is called before RunAsync.
await this.myDictionary.SetAsync(tx, key, value);
await tx.CommitAsync();
}
}
protected override async Task RunAsync(CancellationToken cancellationToken)
{
this.myDictionary = await this.StateManager.GetOrAddAsync<IReliableDictionary<string, string>>("myDictionary");
}
}
I know that I can use the StateManager.GetOrAddAsync method in AddStringToDictionary, but I might want to initialize some more fields. The constructor is not useful either because the StateManager doesn't exist there yet. My current solution is to add a field:
private bool serviceAvailable = false;
I'm setting this field to true at the end of RunAsync. Every public method then calls ThrowIfServiceUnavailable().
private void ThrowIfServiceUnavailable()
{
if (!serviceAvailable)
{
throw new ServiceUnavailableException();
}
}
public async Task AddStringToDictionary(string key, string value)
{
ThrowIfServiceUnavailable();
...
}
Currently I have to handle the ServiceUnavailableException every time I call a method with remoting. My question is: are there any better ways to handle this situation or is this a good solution? And is it possible to add my custom exception to the ServiceProxy's transient exceptions to retry?
Here's an implementation that blocks calls while the service is being initialized. It uses ManualResetEventSlim to block.
And it uses SemaphoreSlim to enforce single threaded access to an async operation.
All Service operations call await WaitForInitializeAsync(CancellationToken.None);
And the implementation of this method is:
private async Task WaitForInitializeAsync(CancellationToken cancellationToken)
{
if (_initializer.IsSet) return;
await Task.Run(() => InitializeAsync(cancellationToken), cancellationToken);
_initializer.Wait(cancellationToken);
}
The implementation of InitializeAsync:
private async Task InitializeAsync(CancellationToken cancellationToken)
{
if (_initializer.IsSet) return;
try
{
_semaphore.Wait(cancellationToken);
if (_initializer.IsSet) return;
[initializer logic here]
In our application_startup, we seed up our database with some fake data, if no data exists.
To do this, we're using the Async methods to store the data. Great. Only problem is, we're not sure how to do this in the application_startup because that's not an async method.
I've spent soooo much time trying to understand #StevenCleary's tutorials and I'm always getting deadlocks. I totally grok what he consistently says:
As a general rule, you should use "async all the way down"; that is, don't block on async code
but I just don't get how I can do that, in this case :(
Lets imagine this is the code I'm trying to play with...
protected void Application_Start()
{
var someFakeData = LoadSomeFakeData();
var documentStore = new DocumentStore();
await documentStore.InitializeAsync(someFakeData);
...
// Registers this database as a singleton.
Container.Register(documentStore);
}
and later on .. some code that uses this documentStore. It is injected via construction injection ...
public SomeController(IDocumentStore documentStore)
{
_documentStore = documentStore;
}
public ViewModel GetFoos()
{
using (var session = _documentStore.OpenSession())
{
... db code goes in here ...
}
}
Clarification
I'm not trying to do some async code in here. I'm actually trying to call this async method, synchronously. Sure, i loose the benefits of async blah blah de blah.. but i'm happy with that. This is start up and I'm happy to block on startup.
In this case, you're asynchronously initializing a shared resource. So, I recommend that you either save the Task itself, or introduce an asynchronous wrapper type.
Using Task:
protected void Application_Start()
{
var someFakeData = LoadSomeFakeData();
var documentStore = new DocumentStore();
var documentStoreTask = documentStore.InitializeAsync(someFakeData);
...
// Registers this database task as a singleton.
Container.Register(documentStoreTask);
}
That may be too awkward, though, depending on Container. In that case, you can introduce an asynchronous wrapper type:
public sealed class DocumentStoreWrapper
{
private readonly Task<DocumentStore> _documentStore;
public DocumentStoreWrapper(Data data)
{
_documentStore = CreateDocumentStoreAsync(data);
}
private static async Task<DocumentStore> CreateDocumentStoreAsync(Data data)
{
var result = new DocumentStore();
await documentStore.InitializeAsync(data);
...
return result;
}
public Task<DocumentStore> DocumentStoreTask { get { return _documentStore; } }
}
protected void Application_Start()
{
var someFakeData = LoadSomeFakeData();
var documentStoreWrapper = new DocumentStoreWrapper(someFakeData);
...
// Registers this database wrapper as a singleton.
Container.Register(documentStoreWrapper);
}
Or, you could use AsyncLazy<T>, which does much the same thing but uses a background thread to execute the initialization code.
You can use of Task.Run(() => YourAsyncMethod()); inside of none async method like:
protected void Application_Start()
{
Task.Run(() => MyAsyncMethod(true));
}
This is an old topic, but it's popped up in my search and maybe it will for others.
For what the OP has requested (ie. To run an async method in a synchronous way from inside a synchronous method, and block until it's finished), is there some reason that the use of Task.WaitAll would not be a simple and adequate way of addressing this?
protected void Application_Start()
{
Task.WaitAll(MyAsyncMethod(true));
}
public static class AsyncHelper
{
private static readonly TaskFactory MyTaskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
return MyTaskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
public static void RunSync(Func<Task> func)
{
MyTaskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
}
then use as
AsyncHelper.RunSync(ProcessAsync);
private async Task ProcessAsync(){ ....