diff --git a/docs/site/docs/getting-started/create-test-project.md b/docs/site/docs/getting-started/create-test-project.md index f85830868..2a173b5a6 100644 --- a/docs/site/docs/getting-started/create-test-project.md +++ b/docs/site/docs/getting-started/create-test-project.md @@ -9,6 +9,67 @@ To write tests, you need a place to put them - a test project. bUnit is not a un To use bUnit, the easiest approach is to use the bUnit project template described in the [Create a test project with bUnit template](#creating-a-test-project-with-bunit-template) section further down the page. To create a test project manually and in a general-purpose testing frameworks agnostic way, read the following section. +## Creating a test project with bUnit template + +To skip a few steps in the guide above, use the [bUnit test project template](https://www.nuget.org/packages/bunit.template/). + +The steps for creating a test project with the bUnit template are as follows: + +1. Install the template (only needed the first time) +2. Create a new test project +3. Add the test project to your solution + +These steps look like this from the `dotnet` CLI: + +**1. Install the template** + +Install the template from NuGet using this command: + +```dotnetcli +dotnet new --install bunit.template +``` + +**2. Create a new test project** + +Use the following command to create a bUnit with xUnit test project: + +# [xUnit](#tab/xunit) + +```dotnetcli +dotnet new bunit --framework xunit -o +``` + +# [NUnit](#tab/nunit) + +```dotnetcli +dotnet new bunit --framework nunit -o +``` + +# [MSTest](#tab/mstest) + +```dotnetcli +dotnet new bunit --framework mstest -o +``` + +*** + +The `--framework` option in the `dotnet new` command above is used to specify the unit testing framework used by the test project. If the `--framework` option is omitted, the default test framework `xunit` will be configured. Currently supported options are the following: + +- `xunit` - [xUnit](https://xunit.net/), +- `nunit` - [NUnit](https://nunit.org/), +- `mstest` - [MSTest](https://docs.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-mstest) + +**3. Add the test project to your solution** + +If using Visual Studio, add the test project to your solution (`.sln`), and add a reference between the test project and the project containing the components that should be tested: + +```dotnetcli +dotnet sln .sln add +dotnet add .csproj reference .csproj +``` + +This will allow the test project to see and test the components in the component project. + ## Creating a test project manually This section will take you through the steps required to create a project for testing Blazor components using bUnit. Any of the three general-purpose test frameworks shown in step 1 below can be used. Briefly, here is what we will do: @@ -116,7 +177,7 @@ The result should be a test project with a `.csproj` that looks like this (non b - + ``` @@ -132,13 +193,13 @@ The result should be a test project with a `.csproj` that looks like this (non b - + - + @@ -158,13 +219,13 @@ The result should be a test project with a `.csproj` that looks like this (non b - + - - + + @@ -172,69 +233,6 @@ The result should be a test project with a `.csproj` that looks like this (non b ``` -*** - -## Creating a test project with bUnit template - -To skip a few steps in the guide above, use the [bUnit test project template](https://www.nuget.org/packages/bunit.template/). - -The steps for creating a test project with the bUnit template are as follows: - -1. Install the template (only needed the first time) -2. Create a new test project -3. Add the test project to your solution - -These steps look like this from the `dotnet` CLI: - -**1. Install the template** - -Install the template from NuGet using this command: - -```dotnetcli -dotnet new install bunit.template::#{NBGV_NuGetPackageVersion}# -``` - -**2. Create a new test project** - -Use the following command to create a bUnit with xUnit test project: - -# [xUnit](#tab/xunit) - -```dotnetcli -dotnet new bunit --framework xunit -o -``` - -# [NUnit](#tab/nunit) - -```dotnetcli -dotnet new bunit --framework nunit -o -``` - -# [MSTest](#tab/mstest) - -```dotnetcli -dotnet new bunit --framework mstest -o -``` - -*** - -The `--framework` option in the `dotnet new` command above is used to specify the unit testing framework used by the test project. If the `--framework` option is omitted, the default test framework `xunit` will be configured. Currently supported options are the following: - -- `xunit` - [xUnit](https://xunit.net/), -- `nunit` - [NUnit](https://nunit.org/), -- `mstest` - [MSTest](https://docs.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-mstest) - -**3. Add the test project to your solution** - -If using Visual Studio, add the test project to your solution (`.sln`), and add a reference between the test project and the project containing the components that should be tested: - -```dotnetcli -dotnet sln .sln add -dotnet add .csproj reference .csproj -``` - -This will allow the test project to see and test the components in the component project. - ## Further reading To start creating tests, continue reading the page. diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 74f317d57..4f3431aa3 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -43,7 +43,7 @@ - + diff --git a/src/bunit.core/Extensions/WaitForHelpers/WaitForHelper.cs b/src/bunit.core/Extensions/WaitForHelpers/WaitForHelper.cs index 9bcd8a277..e32dd7d73 100644 --- a/src/bunit.core/Extensions/WaitForHelpers/WaitForHelper.cs +++ b/src/bunit.core/Extensions/WaitForHelpers/WaitForHelper.cs @@ -9,6 +9,7 @@ namespace Bunit.Extensions.WaitForHelpers; /// public abstract class WaitForHelper : IDisposable { + private readonly Timer timer; private readonly TaskCompletionSource checkPassedCompletionSource; private readonly Func<(bool CheckPassed, T Content)> completeChecker; private readonly IRenderedFragmentBase renderedFragment; @@ -51,7 +52,13 @@ protected WaitForHelper( logger = renderedFragment.Services.CreateLogger>(); checkPassedCompletionSource = new TaskCompletionSource(); - WaitTask = CreateWaitTask(renderedFragment, timeout); + timer = new Timer(_ => + { + logger.LogWaiterTimedOut(renderedFragment.ComponentId); + checkPassedCompletionSource.TrySetException(new WaitForFailedException(TimeoutErrorMessage, capturedException)); + }); + WaitTask = CreateWaitTask(renderedFragment); + timer.Change(GetRuntimeTimeout(timeout), Timeout.InfiniteTimeSpan); InitializeWaiting(); } @@ -80,6 +87,7 @@ protected virtual void Dispose(bool disposing) return; isDisposed = true; + timer.Dispose(); checkPassedCompletionSource.TrySetCanceled(); renderedFragment.OnAfterRender -= OnAfterRender; logger.LogWaiterDisposed(renderedFragment.ComponentId); @@ -105,9 +113,11 @@ private void InitializeWaiting() } } - private Task CreateWaitTask(IRenderedFragmentBase renderedFragment, TimeSpan? timeout) + private Task CreateWaitTask(IRenderedFragmentBase renderedFragment) { - var renderer = renderedFragment.Services.GetRequiredService(); + var renderer = renderedFragment + .Services + .GetRequiredService(); // Two to failure conditions, that the renderer captures an unhandled // exception from a component or itself, or that the timeout is reached, @@ -115,31 +125,18 @@ private Task CreateWaitTask(IRenderedFragmentBase renderedFragment, TimeSpan? // and the continuations does not happen at the same time. var failureTask = renderer.Dispatcher.InvokeAsync(() => { - var taskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); - - var renderException = renderer + return renderer .UnhandledException .ContinueWith( x => Task.FromException(x.Result), CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously, - taskScheduler); - - var timeoutTask = Task.Delay(GetRuntimeTimeout(timeout)) - .ContinueWith( - x => - { - logger.LogWaiterTimedOut(renderedFragment.ComponentId); - return Task.FromException(new WaitForFailedException(TimeoutErrorMessage, capturedException)); - }, - CancellationToken.None, - TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously, - taskScheduler); - - return Task.WhenAny(renderException, timeoutTask).Unwrap(); + TaskScheduler.FromCurrentSynchronizationContext()); }).Unwrap(); - return Task.WhenAny(failureTask, checkPassedCompletionSource.Task).Unwrap(); + return Task + .WhenAny(checkPassedCompletionSource.Task, failureTask) + .Unwrap(); } private void OnAfterRender(object? sender, EventArgs args) @@ -170,7 +167,8 @@ private void OnAfterRender(object? sender, EventArgs args) if (StopWaitingOnCheckException) { - checkPassedCompletionSource.TrySetException(new WaitForFailedException(CheckThrowErrorMessage, capturedException)); + checkPassedCompletionSource.TrySetException( + new WaitForFailedException(CheckThrowErrorMessage, capturedException)); Dispose(); } } diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index 9ed6290d0..677ca95da 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -16,7 +16,7 @@ - + diff --git a/version.json b/version.json index 35c5358b2..bf09bf642 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "1.10", + "version": "1.11-preview", "assemblyVersion": { "precision": "revision" },