forked from ddrilling/AsbCloudServer
Add Tests
This commit is contained in:
parent
7f92f07423
commit
68d3d2724c
@ -52,17 +52,6 @@ public class BackgroundWorker : BackgroundService
|
|||||||
this.serviceProvider = serviceProvider;
|
this.serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Добавить в очередь
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="work"></param>
|
|
||||||
public void Enqueue(Work work)
|
|
||||||
{
|
|
||||||
works.Enqueue(work);
|
|
||||||
if (ExecuteTask is null || ExecuteTask.IsCompleted)
|
|
||||||
StartAsync(CancellationToken.None).Wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken token)
|
protected override async Task ExecuteAsync(CancellationToken token)
|
||||||
{
|
{
|
||||||
while (!token.IsCancellationRequested && works.TryDequeue(out CurrentWork))
|
while (!token.IsCancellationRequested && works.TryDequeue(out CurrentWork))
|
||||||
@ -94,12 +83,27 @@ public class BackgroundWorker : BackgroundService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Добавить в очередь
|
||||||
|
/// <para>
|
||||||
|
/// work.Id может быть не уникальным,
|
||||||
|
/// при этом метод TryRemoveFromQueue удалит все работы с совпадающими id
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="work"></param>
|
||||||
|
public void Enqueue(Work work)
|
||||||
|
{
|
||||||
|
works.Enqueue(work);
|
||||||
|
if (ExecuteTask is null || ExecuteTask.IsCompleted)
|
||||||
|
StartAsync(CancellationToken.None).Wait();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Удаление работы по ID из одноразовой очереди
|
/// Удаление работы по ID из одноразовой очереди
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="id"></param>
|
/// <param name="id"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool TryRemoveFromRunOnceQueue(string id)
|
public bool TryRemoveFromQueue(string id)
|
||||||
{
|
{
|
||||||
var work = Works.FirstOrDefault(w => w.Id == id);
|
var work = Works.FirstOrDefault(w => w.Id == id);
|
||||||
if (work is not null)
|
if (work is not null)
|
||||||
|
@ -14,8 +14,8 @@ namespace AsbCloudInfrastructure.Background;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PeriodicBackgroundWorker : BackgroundService
|
public class PeriodicBackgroundWorker : BackgroundService
|
||||||
{
|
{
|
||||||
private static readonly TimeSpan executePeriod = TimeSpan.FromSeconds(10);
|
private readonly TimeSpan executePeriod = TimeSpan.FromSeconds(10);
|
||||||
private static readonly TimeSpan minDelay = TimeSpan.FromSeconds(1);
|
private readonly TimeSpan minDelay = TimeSpan.FromSeconds(1);
|
||||||
private readonly IServiceProvider serviceProvider;
|
private readonly IServiceProvider serviceProvider;
|
||||||
|
|
||||||
private readonly List<WorkPeriodic> works = new(8);
|
private readonly List<WorkPeriodic> works = new(8);
|
||||||
@ -97,6 +97,8 @@ public class PeriodicBackgroundWorker : BackgroundService
|
|||||||
{
|
{
|
||||||
var periodic = new WorkPeriodic(work, period);
|
var periodic = new WorkPeriodic(work, period);
|
||||||
works.Add(periodic);
|
works.Add(periodic);
|
||||||
|
if (ExecuteTask is null || ExecuteTask.IsCompleted)
|
||||||
|
StartAsync(CancellationToken.None).Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
private WorkPeriodic? GetNext()
|
private WorkPeriodic? GetNext()
|
||||||
|
@ -165,6 +165,7 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddSingleton<ITelemetryDataCache<TelemetryDataSaubDto>>(provider => TelemetryDataCache<TelemetryDataSaubDto>.GetInstance<TelemetryDataSaub>(provider));
|
services.AddSingleton<ITelemetryDataCache<TelemetryDataSaubDto>>(provider => TelemetryDataCache<TelemetryDataSaubDto>.GetInstance<TelemetryDataSaub>(provider));
|
||||||
services.AddSingleton<ITelemetryDataCache<TelemetryDataSpinDto>>(provider => TelemetryDataCache<TelemetryDataSpinDto>.GetInstance<TelemetryDataSpin>(provider));
|
services.AddSingleton<ITelemetryDataCache<TelemetryDataSpinDto>>(provider => TelemetryDataCache<TelemetryDataSpinDto>.GetInstance<TelemetryDataSpin>(provider));
|
||||||
services.AddSingleton<IRequerstTrackerService, RequestTrackerService>();
|
services.AddSingleton<IRequerstTrackerService, RequestTrackerService>();
|
||||||
|
services.AddSingleton<PeriodicBackgroundWorker>();
|
||||||
services.AddSingleton<BackgroundWorker>();
|
services.AddSingleton<BackgroundWorker>();
|
||||||
services.AddSingleton<NotificationBackgroundWorker>();
|
services.AddSingleton<NotificationBackgroundWorker>();
|
||||||
services.AddSingleton<IReduceSamplingService>(provider => ReduceSamplingService.GetInstance(configuration));
|
services.AddSingleton<IReduceSamplingService>(provider => ReduceSamplingService.GetInstance(configuration));
|
||||||
|
@ -556,7 +556,7 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram
|
|||||||
private async Task<int> RemoveDrillingProgramAsync(int idWell, CancellationToken token)
|
private async Task<int> RemoveDrillingProgramAsync(int idWell, CancellationToken token)
|
||||||
{
|
{
|
||||||
var workId = MakeWorkId(idWell);
|
var workId = MakeWorkId(idWell);
|
||||||
backgroundWorker.TryRemoveFromRunOnceQueue(workId);
|
backgroundWorker.TryRemoveFromQueue(workId);
|
||||||
|
|
||||||
var filesIds = await context.Files
|
var filesIds = await context.Files
|
||||||
.Where(f => f.IdWell == idWell &&
|
.Where(f => f.IdWell == idWell &&
|
||||||
|
@ -1,16 +1,7 @@
|
|||||||
using AsbCloudApp.Data;
|
using AsbCloudInfrastructure.Background;
|
||||||
using AsbCloudApp.Data.SAUB;
|
|
||||||
using AsbCloudApp.Repositories;
|
|
||||||
using AsbCloudApp.Requests;
|
|
||||||
using AsbCloudApp.Services;
|
|
||||||
using AsbCloudInfrastructure.Background;
|
|
||||||
using AsbCloudInfrastructure.Services;
|
|
||||||
using AsbCloudInfrastructure.Services.SAUB;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -18,12 +9,12 @@ using Xunit;
|
|||||||
|
|
||||||
namespace AsbCloudWebApi.Tests.Services;
|
namespace AsbCloudWebApi.Tests.Services;
|
||||||
|
|
||||||
public class BackgroundWorkertest
|
public class BackgroundWorkerTest
|
||||||
{
|
{
|
||||||
private IServiceProvider provider;
|
private IServiceProvider provider;
|
||||||
private BackgroundWorker service;
|
private BackgroundWorker service;
|
||||||
|
|
||||||
public BackgroundWorkertest()
|
public BackgroundWorkerTest()
|
||||||
{
|
{
|
||||||
provider = Substitute.For<IServiceProvider, ISupportRequiredService>();
|
provider = Substitute.For<IServiceProvider, ISupportRequiredService>();
|
||||||
var serviceScope = Substitute.For<IServiceScope>();
|
var serviceScope = Substitute.For<IServiceScope>();
|
||||||
@ -33,7 +24,7 @@ public class BackgroundWorkertest
|
|||||||
|
|
||||||
service = new BackgroundWorker(provider);
|
service = new BackgroundWorker(provider);
|
||||||
typeof(BackgroundWorker)
|
typeof(BackgroundWorker)
|
||||||
.GetField("minDelay", BindingFlags.NonPublic | BindingFlags.Instance)?
|
.GetField("minDelay", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
.SetValue(service, TimeSpan.FromMilliseconds(1));
|
.SetValue(service, TimeSpan.FromMilliseconds(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +46,7 @@ public class BackgroundWorkertest
|
|||||||
service.Enqueue(work);
|
service.Enqueue(work);
|
||||||
}
|
}
|
||||||
|
|
||||||
var waitI = workCount;
|
await service.ExecuteTask;
|
||||||
await Task.Delay(1_000);
|
|
||||||
//while (waitI-- > 0 && service.ExecuteTask is not null && service.ExecuteTask.IsCompleted)
|
|
||||||
// await Task.Delay(4);
|
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(workCount, result);
|
Assert.Equal(workCount, result);
|
||||||
@ -69,15 +57,16 @@ public class BackgroundWorkertest
|
|||||||
{
|
{
|
||||||
var expectadResult = 42;
|
var expectadResult = 42;
|
||||||
var result = 0;
|
var result = 0;
|
||||||
|
|
||||||
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
||||||
{
|
{
|
||||||
result = expectadResult;
|
result = expectadResult;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
var goodWork = Work.CreateByDelegate("", workAction);
|
||||||
|
|
||||||
Task failAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
Task failAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
||||||
=> throw new Exception();
|
=> throw new Exception();
|
||||||
var goodWork = Work.CreateByDelegate("", workAction);
|
|
||||||
|
|
||||||
var badWork = Work.CreateByDelegate("", failAction);
|
var badWork = Work.CreateByDelegate("", failAction);
|
||||||
badWork.OnErrorAsync = (id, exception, token) => throw new Exception();
|
badWork.OnErrorAsync = (id, exception, token) => throw new Exception();
|
||||||
@ -85,9 +74,40 @@ public class BackgroundWorkertest
|
|||||||
//act
|
//act
|
||||||
service.Enqueue(badWork);
|
service.Enqueue(badWork);
|
||||||
service.Enqueue(goodWork);
|
service.Enqueue(goodWork);
|
||||||
await Task.Delay(1200);
|
|
||||||
|
await service.ExecuteTask;
|
||||||
|
|
||||||
//assert
|
//assert
|
||||||
Assert.Equal(expectadResult, result);
|
Assert.Equal(expectadResult, result);
|
||||||
|
Assert.Equal(1, service.Felled.Count);
|
||||||
|
Assert.Equal(1, service.Done.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task TryRemove()
|
||||||
|
{
|
||||||
|
var workCount = 5;
|
||||||
|
var result = 0;
|
||||||
|
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
||||||
|
{
|
||||||
|
result++;
|
||||||
|
return Task.Delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
//act
|
||||||
|
for (int i = 0; i < workCount; i++)
|
||||||
|
{
|
||||||
|
var work = Work.CreateByDelegate(i.ToString(), workAction);
|
||||||
|
service.Enqueue(work);
|
||||||
|
}
|
||||||
|
|
||||||
|
var removed = service.TryRemoveFromQueue((workCount - 1).ToString());
|
||||||
|
|
||||||
|
await service.ExecuteTask;
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.True(removed);
|
||||||
|
Assert.Equal(workCount - 1, result);
|
||||||
|
Assert.Equal(workCount - 1, service.Done.Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,97 @@
|
|||||||
|
using AsbCloudInfrastructure.Background;
|
||||||
|
using DocumentFormat.OpenXml.Drawing.Charts;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using NSubstitute;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Tests.Services;
|
||||||
|
|
||||||
|
public class PeriodicBackgroundWorkerTest
|
||||||
|
{
|
||||||
|
private IServiceProvider provider;
|
||||||
|
private PeriodicBackgroundWorker service;
|
||||||
|
|
||||||
|
public PeriodicBackgroundWorkerTest()
|
||||||
|
{
|
||||||
|
provider = Substitute.For<IServiceProvider, ISupportRequiredService>();
|
||||||
|
var serviceScope = Substitute.For<IServiceScope>();
|
||||||
|
var serviceScopeFactory = Substitute.For<IServiceScopeFactory>();
|
||||||
|
serviceScopeFactory.CreateScope().Returns(serviceScope);
|
||||||
|
((ISupportRequiredService)provider).GetRequiredService(typeof(IServiceScopeFactory)).Returns(serviceScopeFactory);
|
||||||
|
|
||||||
|
service = new PeriodicBackgroundWorker(provider);
|
||||||
|
typeof(PeriodicBackgroundWorker)
|
||||||
|
.GetField("minDelay", BindingFlags.NonPublic | BindingFlags.Instance)?
|
||||||
|
.SetValue(service, TimeSpan.FromMilliseconds(1));
|
||||||
|
|
||||||
|
typeof(PeriodicBackgroundWorker)
|
||||||
|
.GetField("executePeriod", BindingFlags.NonPublic | BindingFlags.Instance)?
|
||||||
|
.SetValue(service, TimeSpan.FromMilliseconds(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task WorkRunsTwice()
|
||||||
|
{
|
||||||
|
var workCount = 2;
|
||||||
|
var periodMs = 100d;
|
||||||
|
|
||||||
|
var period = TimeSpan.FromMilliseconds(periodMs);
|
||||||
|
|
||||||
|
var result = 0;
|
||||||
|
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
||||||
|
{
|
||||||
|
result++;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
//act
|
||||||
|
var work = Work.CreateByDelegate("", workAction);
|
||||||
|
|
||||||
|
var stopwatch = Stopwatch.StartNew();
|
||||||
|
service.Add(work, period);
|
||||||
|
|
||||||
|
var delay = (periodMs / 20) + (periodMs * workCount) - stopwatch.ElapsedMilliseconds;
|
||||||
|
await Task.Delay(TimeSpan.FromMilliseconds(delay));
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.Equal(workCount, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Enqueue_continues_after_exceptions()
|
||||||
|
{
|
||||||
|
var expectadResult = 42;
|
||||||
|
var result = 0;
|
||||||
|
|
||||||
|
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
||||||
|
{
|
||||||
|
result = expectadResult;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
var goodWork = Work.CreateByDelegate("", workAction);
|
||||||
|
|
||||||
|
Task failAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
||||||
|
=> throw new Exception();
|
||||||
|
|
||||||
|
var badWork = Work.CreateByDelegate("", failAction);
|
||||||
|
badWork.OnErrorAsync = (id, exception, token) => throw new Exception();
|
||||||
|
|
||||||
|
//act
|
||||||
|
service.Add(badWork, TimeSpan.FromSeconds(2));
|
||||||
|
service.Add(goodWork, TimeSpan.FromSeconds(2));
|
||||||
|
|
||||||
|
await Task.Delay(TimeSpan.FromMilliseconds(20));
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.Equal(expectadResult, result);
|
||||||
|
Assert.Equal(1, badWork.CountErrors);
|
||||||
|
Assert.Equal(1, goodWork.CountComplete);
|
||||||
|
Assert.Equal(1, goodWork.CountStart);
|
||||||
|
}
|
||||||
|
}
|
126
AsbCloudWebApi.Tests/Services/WorkTest.cs
Normal file
126
AsbCloudWebApi.Tests/Services/WorkTest.cs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
using AsbCloudInfrastructure.Background;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using NSubstitute;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace AsbCloudWebApi.Tests.Services
|
||||||
|
{
|
||||||
|
public class WorkTest
|
||||||
|
{
|
||||||
|
private IServiceProvider provider;
|
||||||
|
|
||||||
|
public WorkTest()
|
||||||
|
{
|
||||||
|
provider = Substitute.For<IServiceProvider, ISupportRequiredService>();
|
||||||
|
var serviceScope = Substitute.For<IServiceScope>();
|
||||||
|
var serviceScopeFactory = Substitute.For<IServiceScopeFactory>();
|
||||||
|
serviceScopeFactory.CreateScope().Returns(serviceScope);
|
||||||
|
((ISupportRequiredService)provider).GetRequiredService(typeof(IServiceScopeFactory)).Returns(serviceScopeFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Work_done_with_success()
|
||||||
|
{
|
||||||
|
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
||||||
|
=> Task.CompletedTask;
|
||||||
|
|
||||||
|
var work = Work.CreateByDelegate("", workAction);
|
||||||
|
|
||||||
|
//act
|
||||||
|
var begin = DateTime.Now;
|
||||||
|
await work.Start(provider, CancellationToken.None);
|
||||||
|
var done = DateTime.Now;
|
||||||
|
var executionTime = done - begin;
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.Equal(1, work.CountComplete);
|
||||||
|
Assert.Equal(1, work.CountStart);
|
||||||
|
Assert.Equal(0, work.CountErrors);
|
||||||
|
Assert.Null(work.CurrentState);
|
||||||
|
Assert.Null(work.LastError);
|
||||||
|
|
||||||
|
var lastState = work.LastComplete;
|
||||||
|
Assert.NotNull(lastState);
|
||||||
|
Assert.InRange(lastState.Start, begin, done - 0.5 * executionTime);
|
||||||
|
Assert.InRange(lastState.End, done - 0.5 * executionTime, done);
|
||||||
|
Assert.InRange(lastState.ExecutionTime, TimeSpan.Zero, executionTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Work_calls_callback()
|
||||||
|
{
|
||||||
|
var expectedState = "42";
|
||||||
|
var expectedProgress = 42d;
|
||||||
|
|
||||||
|
var timeout = TimeSpan.FromMilliseconds(40);
|
||||||
|
|
||||||
|
Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
||||||
|
{
|
||||||
|
callback.Invoke(expectedState, expectedProgress);
|
||||||
|
return Task.Delay(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
var work = Work.CreateByDelegate("", workAction);
|
||||||
|
|
||||||
|
//act
|
||||||
|
var begin = DateTime.Now;
|
||||||
|
_ = work.Start(provider, CancellationToken.None);
|
||||||
|
await Task.Delay(timeout/3);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.Equal(0, work.CountComplete);
|
||||||
|
Assert.Equal(1, work.CountStart);
|
||||||
|
Assert.Equal(0, work.CountErrors);
|
||||||
|
Assert.NotNull(work.CurrentState);
|
||||||
|
Assert.Null(work.LastComplete);
|
||||||
|
Assert.Null(work.LastError);
|
||||||
|
|
||||||
|
var currentState = work.CurrentState;
|
||||||
|
Assert.NotNull(currentState);
|
||||||
|
Assert.InRange(currentState.Start, begin, begin + timeout);
|
||||||
|
Assert.InRange(currentState.StateUpdate, begin, begin + timeout);
|
||||||
|
Assert.Equal(expectedState, currentState.State);
|
||||||
|
Assert.Equal(expectedProgress, currentState.Progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Work_fails_with_info()
|
||||||
|
{
|
||||||
|
var expectedState = "41";
|
||||||
|
var expectedErrorText = "42";
|
||||||
|
var minWorkTime = TimeSpan.FromMilliseconds(10);
|
||||||
|
|
||||||
|
async Task workAction(string id, IServiceProvider services, Action<string, double?> callback, CancellationToken token)
|
||||||
|
{
|
||||||
|
await Task.Delay(minWorkTime);
|
||||||
|
callback(expectedState, 0);
|
||||||
|
throw new Exception(expectedErrorText);
|
||||||
|
}
|
||||||
|
|
||||||
|
var work = Work.CreateByDelegate("", workAction);
|
||||||
|
|
||||||
|
//act
|
||||||
|
var begin = DateTime.Now;
|
||||||
|
await work.Start(provider, CancellationToken.None);
|
||||||
|
|
||||||
|
//assert
|
||||||
|
Assert.Equal(0, work.CountComplete);
|
||||||
|
Assert.Equal(1, work.CountStart);
|
||||||
|
Assert.Equal(1, work.CountErrors);
|
||||||
|
Assert.Null(work.CurrentState);
|
||||||
|
Assert.Null(work.LastComplete);
|
||||||
|
|
||||||
|
var error = work.LastError;
|
||||||
|
Assert.NotNull(error);
|
||||||
|
Assert.InRange(error.Start, begin, DateTime.Now);
|
||||||
|
Assert.InRange(error.End, begin, DateTime.Now);
|
||||||
|
Assert.InRange(error.ExecutionTime, minWorkTime, DateTime.Now - begin);
|
||||||
|
Assert.Contains(expectedErrorText, error.ErrorText, StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
Assert.Equal(expectedState, error.State);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user