I am using xunit to do integration testing, and below is my test class.
public class CodesAndGuidelinesTest : IClassFixture<SchemaCache>
{
public readonly SchemaCache schemaCache;
public CodesAndGuidelinesTest(PostgreSqlResource resource)
{
schemaCache = new SchemaCache(resource);
}
[Fact]
public async Task Create_Name_Contains_Expression()
{
IRequestExecutor requestExecutor = await schemaCache.CodesAndGuidelinesExecutor;
.......
}
}
Here is the schema cache class
public class SchemaCache : QueryTestBase
{
Task<IRequestExecutor> _codesAndGuidelinesExecutor;
public SchemaCache(PostgreSqlResource resource) : base(resource)
{
_codesAndGuidelinesExecutor = CreateDb(CodesAndGuidelinesMockFixture.codeStandardGuidelines);
}
public Task<IRequestExecutor> CodesAndGuidelinesExecutor
{
get { return _codesAndGuidelinesExecutor; }
}
}
Here CodesAndGuidelinesMockFixture.codeStandardGuidelines is just a mock object, and When I run the test cases, I am getting the below error.
Class fixture type 'API.Tests.SchemaCache` had one or more unresolved
constructor arguments: PostgreSqlResource resource,
CodeStandardGuideline[] codesAndGuidelines The following
constructor parameters did not have matching fixture data:
PostgreSqlResource resource
I am not sure where I am doing wrong with the above code. Could anyone point me in the right direction?
Thanks!!!
Update :
QueryTestBase class
public class QueryTestBase
{
private readonly PostgreSqlResource _resource;
public QueryTestBase(PostgreSqlResource resource)
{
_resource = resource;
}
protected async Task<Func<IResolverContext, IQueryable<T>>> BuildResolverAsync<T>(T[] arrayOfEntities) where T : class
{
var databaseName = Guid.NewGuid().ToString("N");
var options = new DbContextOptionsBuilder<APIDbContext>()
.UseNpgsql(_resource.ConnectionString)
.Options;
.......
.......
return _ => set.AsQueryable();
}
protected async Task<IRequestExecutor> CreateDb<T>(T[] Entities) where T : class
{
Func<IResolverContext, IQueryable<T>> resolver = await BuildResolverAsync(Entities);
return .......
}
}
Your tool (Squadron) provides an easy way to have a PostgreSqlResource.
This resource has this properties:
implement standard IDisposable interface (or xunit speficIAsyncLifetime interface)
has a parameterless contructor
// sync implementation
class PostgreSqlResource : IDisposable
{
public PostgreSqlResource()
{
// init code
}
// props and logic
public Dispose()
{
// dispose code
}
}
// async implementation
class PostgreSqlResource : IAsyncLifetime
{
public PostgreSqlResource()
{
}
public async Task InitializeAsync()
{
// init code
}
// props and logic
public async Task DisposeAsync()
{
// dispose code
}
}
This object can be shared in xunit in 3 way:
for each test: create fixture, execute test, dispose fixture
for each class: create fixture, execute tests inside a class, dispose fixture
for a set of classes: create fixture, execute marked test classes, dispose fixture
In your case you need the 3rd way.
So Squadron provide a fixture for you, jou just need to define a TestCollection to mark your classes.
[CollectionDefinition("Squadron")]
public class DatabaseCollection : ICollectionFixture<PostgreSqlResource>
{
// This class has no code, and is never created. Its purpose is simply
// to be the place to apply [CollectionDefinition] and all the
// ICollectionFixture<> interfaces.
}
and after that you can simply tag your test classes with attribute [Collection("Squadron")] that allow you in inject via constructor the shared instance.
[Collection("Squadron")]
public class DatabaseTestClass1
{
PostgreSqlResource fixture;
public DatabaseTestClass1(PostgreSqlResource fixture)
{
this.fixture = fixture;
}
}
[Collection("Squadron")]
public class DatabaseTestClass2
{
// ...
In case PostgreSqlResource is not enought and you need a more complex fixture is very easy; you can just create your own fixture around the other.
Of course you need to implement the same interface and delegate implementation to inner member.
class ComplexFixture: IAsyncLifetime
{
private PostgreSqlResource _pg;
public ComplexFixture()
{
_pg = new PostgreSqlResource();
}
// fixture methods
public async Task InitializeAsync()
{
await _pg.InitializeAsync();
}
public async Task DisposeAsync()
{
await _pg.DisposeAsync();
}
}
And refer to ComplexFixture insted of PostgreSqlResource on xunit CollectionFixtures. This approach is not suggested.
In my opinion is better a Plain fixture injected to test class, and than wrapped in a class fixture object if needed.
[Collection("Squadron")]
public class DatabaseTestClass1 : IDisposable
{
// each test lifecycle
private MyComplexFixture _fixture;
// global lifecycle
public DatabaseTestClass1(DatabaseFixture dbFixture)
{
_fixture = new MyComplexFixture(dbFixture)
}
// tests
public Dispose()
{
// this can reset db state for a new test
_fixture.Dispose();
}
}
public class MyComplexFixture : IDisposable
{
public MyComplexFixture (DatabaseFixture dbFixture)
{
// ...
}
public Dispose()
{
// reset logic like DROP TABLE EXECUTION
// Please note that dbFixture shoul no be disposed here!
// xunit will dispose class after all executions.
}
}
So applying this solution to your code can be as follows.
[CollectionDefinition("SquadronSchemaCache")]
public class DatabaseCollection : ICollectionFixture<SchemaCache>
{
}
[Collection("SquadronSchemaCache")]
public class CodesAndGuidelinesTest
{
public readonly SchemaCache schemaCache;
public CodesAndGuidelinesTest(SchemaCache resource)
{
this.schemaCache = schemaCache;
}
[Fact]
public async Task Create_Name_Contains_Expression()
{
IRequestExecutor requestExecutor = await schemaCache.CodesAndGuidelinesExecutor;
.......
}
}
public class SchemaCache : QueryTestBase
{
Task<IRequestExecutor> _codesAndGuidelinesExecutor;
public SchemaCache() : base(new PostgreSqlResource())
{
_codesAndGuidelinesExecutor = CreateDb(CodesAndGuidelinesMockFixture.codeStandardGuidelines);
}
public Task<IRequestExecutor> CodesAndGuidelinesExecutor
{
get { return _codesAndGuidelinesExecutor; }
}
}
public class QueryTestBase : IAsyncLifetime
{
private readonly PostgreSqlResource _resource;
public QueryTestBase(PostgreSqlResource resource)
{
_resource = resource;
}
protected async Task<Func<IResolverContext, IQueryable<T>>> BuildResolverAsync<T>(T[] arrayOfEntities) where T : class
{
var databaseName = Guid.NewGuid().ToString("N");
var options = new DbContextOptionsBuilder<APIDbContext>()
.UseNpgsql(_resource.ConnectionString)
.Options;
.......
.......
return _ => set.AsQueryable();
}
protected async Task<IRequestExecutor> CreateDb<T>(T[] Entities) where T : class
{
Func<IResolverContext, IQueryable<T>> resolver = await BuildResolverAsync(Entities);
return .......
}
public async Task InitializeAsync()
{
await _resource.InitializeAsync();
}
public async Task DisposeAsync()
{
_resource.Dispose()
}
}
I'm trying to make a generic implementation of kafka consumers in .NET. Basically I don't want to have a consumer for each and every type of message. I want a generic consumer and then the logic of handling the message is in actual Handlers.
What I tried:
Create a generic interface for handlers
public interface IKafkaHandler<TKey, TMessage>
{
Task HandleAsync(TKey key, TMessage message);
}
Create a concrete handler
public class ClubMessageHandler : IKafkaHandler<string, ClubMessage>
{
private readonly ILogger _logger;
public ClubMessageHandler(ILogger logger)
{
_logger = logger;
}
public Task HandleAsync(string key, ClubMessage message)
{
_logger.LogInformation($"Let's go {message.Name}");
return Task.CompletedTask;
}
}
Create a generic consumer
public class GenericConsumer<TKey, TMessage> : BackgroundService
where TKey: class
where TMessage : class
{
private readonly IKafkaHandler<TKey, TMessage> _handler;
public GenericConsumer(IKafkaHandler<TKey, TMessage> handler)
{
_handler = handler;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
var conf = new ConsumerConfig
{
GroupId = "st_consumer_group",
BootstrapServers = "localhost:9092",
AutoOffsetReset = AutoOffsetReset.Earliest
};
using (var builder = new ConsumerBuilder<TKey, TMessage>(conf).Build())
{
builder.Subscribe("topic.name");
var cancelToken = new CancellationTokenSource();
try
{
while (true)
{
var consumer = builder.Consume(stoppingToken);
//here I want to inject the correct handler based on TMessage type
_handler.HandleAsync(consumer.Message.Key, consumer.Message.Value);
}
}
catch (Exception)
{
builder.Close();
}
}
return Task.CompletedTask;
}
}
And this is where I kinda got stuck. If I try in Program.cs
builder.Services.AddSingleton<IKafkaHandler<string, ClubMessage>, ClubMessageHandler>();
I get an exception saying it can't resolve the services (I can post the entire message if needed)
In the end what I want to achieve is to be able to have something like
//Inject Handlers
builder.Services.AddSingleton<IKafkaHandler<string, ClubMessage>, ClubMessageHandler>();
builder.Services.AddSingleton<IKafkaHandler<string, PlayerMessage>, PlayerMessageHandler>();
builder.Services.AddSingleton<IKafkaHandler<string, OtherMessage>, OtherMessageHandler>();
//Start background services
builder.Services.AddSingleton<GenericConsumer<string, ClubMessage>, ClubMessageHandler>();
//etc...
At this point I'm not even sure if this is possible(although it probably is)? I'm not really sure what I'm missing here. What's the correct way to have use dependency injection here?
I'm trying to make an unit test for a logger in an application.
For example I need to test the method Logger.info("some message"), but this method is static and return void.
Searching on Google I understand that I have to use Moq but am unable to implement that on the UnitTest class.
The Logger constructor does not have an argument and in x.Debug I have an error that says that I can't access
from instance reference.
Is there a way to implement UnitTest without editing the production code?
[TestClass()]
public class LoggerTests
{
[TestMethod()]
public void DebugTest()
{
var mock = new Mock<Logger>();
mock.Setup(x => x.Debug(It.IsAny<string>());
new Logger(mock.Object).AddLog("testing");
mock.VerifyAll;
}
}
Program.cs
private static void ConfigureLogger()
{
Logger.AddLog(new NLogAppender());
Logger.Level = TraceLevel.Verbose;
Logger.Info("Configured Logger");
}
Logger.cs
public class Logger
{
public static readonly List<IAppender> loggings = new List<IAppender>();
public static void AddLog(IAppender appender)
{
loggings.Add(appender);
}
public static TraceLevel Level { get; set; }
static Logger()
{
Level = TraceLevel.Verbose;
}
public static void Info(string message)
{
LogMessage(message);
}
}
NlogAppender.cs
public class NLogAppender : IAppender
{
public NLog.Logger logger;
public NLogAppender()
{
logger = LogManager.GetLogger(nameof(NLogAppender));
}
public void AddLog(string str)
{
}
}
IAppender.cs
public interface IAppender
{
void AddLog(string str);
}
You can't mock a static class, and you shouldn't mock the class/system under test.
Add a mock appender to the logger:
// Arrange
var logString = "test-info"
var appenderMock = new Mock<IAppender>();
appenderMock.Setup(a => a.AddLog(logString));
Logger.AddLog(appenderMock.Object);
// Act
Logger.Info(logString);
// Assert
// TODO: exactly once
appenderMock.VerifyAll();
Note this static class may persist data between tests causing unexpected results, consult your test framework for configuring this.
Apart from that, you usually don't want to roll your own logging infrastructure, there's lots of things you can do wrong and why reinvent the wheel? Plenty of ILogger(<T>) implementations around.
I have a console app which uses a class library to execute some long running tasks. This is a .net core console app and uses the .net core Generic Host. I also use the ShellProgressBar library to display some progress bars.
My Hosted service looks like this
internal class MyHostedService : IHostedService, IDisposable
{
private readonly ILogger _logger;
private readonly IMyService _myService;
private readonly IProgress<MyCustomProgress> _progress;
private readonly IApplicationLifetime _appLifetime;
private readonly ProgressBar _progressBar;
private readonly IProgressBarFactory _progressBarFactory;
public MyHostedService(
ILogger<MyHostedService> logger,
IMyService myService,
IProgressBarFactory progressBarFactory,
IApplicationLifetime appLifetime)
{
_logger = logger;
_myService = myService;
_appLifetime = appLifetime;
_progressBarFactory = progressBarFactory;
_progressBar = _progressBarFactory.GetProgressBar(); // this just returns an instance of ShellProgressBar
_progress = new Progress<MyCustomProgress>(progress =>
{
_progressBar.Tick(progress.Current);
});
}
public void Dispose()
{
_progressBar.Dispose();
}
public Task StartAsync(CancellationToken cancellationToken)
{
_myService.RunJobs(_progress);
_appLifetime.StopApplication();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
Where MyCustomProgress looks like this
public class MyCustomProgress
{
public int Current {get; set;}
public int Total {get; set;}
}
and MyService looks something like so (Job1, Job2, Job3 implement IJob)
public class MyService : IMyService
{
private void List<IJob> _jobsToRun;
public MyService()
{
_jobsToRun.Add(new Job1());
_jobsToRun.Add(new Job2());
_jobsToRun.Add(new Job3());
}
public void RunJobs(IProgress<MyCustomProgress> progress)
{
_jobsToRun.ForEach(job =>
{
job.Execute();
progress.Report(new MyCustomProgress { Current = _jobsToRun.IndexOf(job) + 1, Total = _jobsToRun.Count() });
});
}
}
And IJob is
public interface IJob
{
void Execute();
}
This setup works well and I'm able to display the progress bar from my HostedService by creating a ShellProgressBar instance and using the one IProgress instance I have to update it.
However, I have another implementation of IMyService that I also need to run that looks something like this
public class MyService2 : IMyService
{
private void List<IJob> _sequentialJobsToRun;
private void List<IJob> _parallelJobsToRun;
public MyService()
{
_sequentialJobsToRun.Add(new Job1());
_sequentialJobsToRun.Add(new Job2());
_sequentialJobsToRun.Add(new Job3());
_parallelJobsToRun.Add(new Job4());
_parallelJobsToRun.Add(new Job5());
_parallelJobsToRun.Add(new Job6());
}
public void RunJobs(IProgress<MyCustomProgress> progress)
{
_sequentialJobsToRun.ForEach(job =>
{
job.Execute();
progress.Report(new MyCustomProgress { Current = _jobsToRun.IndexOf(job) + 1, Total = _jobsToRun.Count() });
});
Parallel.ForEach(_parallelJobsToRun, job =>
{
job.Execute();
// Report progress here
});
}
}
This is the one I'm struggling with. when _parallelJobsToRun is executed, I need to be able to create a new child ShellProgressBar (ShellProgressBar.Spawn) and display them as child progress bars of let's say 'Parallel Jobs'.
This is where I'm looking for some help as to how I can achieve this.
Note: I don't want to take a dependency on ShellProgressBar in my class library containing MyService
Any help much appreciated.
I am a little confused by your description, but let's see if I understand what you are up to. So if you wrap all of this in a class, then taskList1 and taskList2 could be class variables. (By the way taskList1/2 should be named better: say parallelTaskList and whatever . . . anyway.) Then you could write a new method on the class CheckTaskStatus() and just iterate over the two class variables. Does that help or have I completely missed your question?
Can you modify it like this?
public Task<ICollection<IProgress<int>>> StartAsync(CancellationToken cancellationToken)
{
var progressList = _myServiceFromLibrary.RunTasks();
return Task.FromResult(progressList);
}
public ICollection<IProgress<int>> RunTasks()
{
var taskList1 = new List<ITask> { Task1, Task2 };
var plist1 = taskList1.Select(t => t.Progress).ToList();
var taskList2 = new List<ITask> { Task3, Task4, Task5 }:
var plist2 = taskList2.Select(t => t.Progress).ToList();
taskList1.foreach( task => task.Run() );
Parallel.Foreach(taskList2, task => { task.Run() });
return plist1.Concat(plist2).ToList();
}
Task.Progress there is probably a progress getter. realistically IProgress should probably be injected via Tasks constructors. But the point is your public interface doesn't accept list of tasks, thus it should just return collection of progress reports.
How to inject progress reporters into your tasks is a different story that depends on tasks implementations and it may or may not be supported. out of the box.
However what you probably should do is to supply progress callback or progress factory so that progress reporters of your choice are created:
public Task StartAsync(CancellationToken cancellationToken, Action<Task,int> onprogress)
{
_myServiceFromLibrary.RunTasks(onprogress);
return Task.CompletedTask;
}
public class SimpleProgress : IProgress<int>
{
private readonly Task task;
private readonly Action<Task,int> action;
public SimpleProgress(Task task, Action<Task,int> action)
{
this.task = task;
this.action = action;
}
public void Report(int progress)
{
action(task, progress);
}
}
public ICollection<IProgress<int>> RunTasks(Action<Task,int> onprogress)
{
var taskList1 = new List<ITask> { Task1, Task2 };
taskList1.foreach(t => t.Progress = new SimpleProgress(t, onprogress));
var taskList2 = new List<ITask> { Task3, Task4, Task5 }:
taskList2.foreach(t => t.Progress = new SimpleProgress(t, onprogress));
taskList1.foreach( task => task.Run() );
Parallel.Foreach(taskList2, task => { task.Run() });
}
you may see here, that it really is mostly question about how your tasks are going to call IProgress<T>.Report(T value) method.
Honestly I would just use an event in your task prototype.
It's not really clear exactly what you want because the code you posted doesn't match the names you then reference in your question text... It would be helpful to have all the code (the RunTasks function for example, your IProgress prototype, etc).
Nevertheless, an event exists specifically to signal calling code. Let's go back to the basics. Let's say you have library called MyLib, with a method DoThings().
Create a new class that inherits from EventArgs, and that will carry your task's progress reports...
public class ProgressEventArgs : EventArgs
{
private int _taskId;
private int _percent;
private string _message;
public int TaskId => _taskId;
public int Percent => _percent;
public string Message => _message;
public ProgressEventArgs(int taskId, int percent, string message)
{
_taskId = taskId;
_percent = percent;
_message = message;
}
}
Then on your library's class definition, add an event like so:
public event EventHandler<ProgressEventArgs> Progress;
And in your console application, create a handler for progress events:
void ProgressHandler(object sender, ProgressEventArgs e)
{
// Do whatever you want with your progress report here, all your
// info is in the e variable
}
And subscribe to your class library's event:
var lib = new MyLib();
lib.Progress += ProgressHandler;
lib.DoThings();
When you are done, unsubscribe from the event:
lib.Progress -= ProgressHandler;
In your class library, now you can send back progress reports by raising the event in your code. First create a stub method to invoke the event:
protected virtual void OnProgress(ProgressEventArgs e)
{
var handler = Progress;
if (handler != null)
{
handler(this, e);
}
}
And then add this to your task's code where you want it:
OnProgress(new ProgressEventArgs(2452343, 10, "Reindexing google..."));
The only thing to be careful about is to report progress sparingly, because each time your event fires it interrupts your console application, and you can really bog it down hard if you send 10 million events all at once. Be logical about it.
Alternate way; If you own the code IProgress<T> and Progress
IProgress<T>
{
IProgress<T> CreateNew();
Report(T progress);
}
Progress<T> : IProgress<T>
{
Progress(ShellProgressClass)
{
// initialize progressBar or span new
}
....
IProgress<T> CreateNew()
{
return new Progress();
}
}
you can later improvise to have one big progressBar (collection of Sequential or Parallel) and what not
Your MyService could have a dependency similar to:
public interface IJobContainer
{
void Add(IJob job);
void RunJobs(IProgress<MyProgress> progress, Action<IJob>? callback = null); // Using an action for extra work you may want to do
}
This way you don't have to worry about reporting progress in MyService (which doesn't feel like it should be MyService's job anyway. The implementation could look something like this for the parallel job container:
public class MyParallelJobContainer
{
private readonly IList<IJob> parallelJobs = new List<IJob>();
public MyParallelJobContainer()
{
this.progress = progress;
}
public void Add(IJob job) { ... }
void RunJobs(IProgress<MyProgress> progress, Action<IJob>? callback = null)
{
using (var progressBar = new ProgressBar(options...))
{
Parallel.ForEach(parallelJobs, job =>
{
callback?.Invoke(job);
job.Execute();
progressBar.Tick();
})
}
}
}
MyService would then look like this:
public class MyService : IMyService
{
private readonly IJobContainer sequentialJobs;
private readonly IJobContainer parallelJobs;
public MyService(
IJobContainer sequentialJobs,
IJobContainer parallelJobs)
{
this.sequentialJobs = sequentialJobs;
this.parallelJobs = parallelJobs;
this.sequentialJobs.Add(new DoSequentialJob1());
this.sequentialJobs.Add(new DoSequentialJob2());
this.sequentialJobs.Add(new DoSequentialJob3));
this.parallelJobs.Add(new DoParallelJobA());
this.parallelJobs.Add(new DoParallelJobB());
this.parallelJobs.Add(new DoParallelJobC());
}
public void RunJobs(IProgress<MyCustomProgress> progress)
{
sequentialJobs.RunJobs(progress, job =>
{
// do something with the job if necessary
});
parallelJobs.RunJobs(progress, job =>
{
// do something with the job if necessary
});
}
The advantage of this way is that MyService only has one job and doesn't have to worry about what you do once the job is completed.
From my understanding of your issue the question is how do you display progress across both completion of the synchronous jobs and parallelized jobs.
In theory the parallel jobs could start and finish at the same time, so you could treat the parallel jobs as a single job. Instead of using the count of sequential jobs as your total, increase that number by one. This might be satisfactory for a small number of parallel jobs.
If you want to add progress between the parallel jobs, you will need to handle multi-threading in your code because the parallel jobs will be running concurrently.
object pJobLock = new object();
int numProcessed = 0;
foreach(var parallelJob in parallelJobs)
{
parallelJob.DoWork();
lock (pJobLock)
{
numProcessed++;
progress.Report(new MyCustomProgress { Current = numProcessed, Total = parallelJobs.Count() });
}
}
I have a conditional statement which should looks as follows:
//...
if(_view.VerifyData != true)
{
//...
}
else
{
_view.PermanentCancellation.Cancel();
}
where PermanentCancellation is of type CancellationTokenSource.
Im wondering how i should set this up in my mock of _view. All attempts thus far have failed :( and i cant find an example on google.
Any pointers would be appreciated.
Because CancellationTokenSource.Cancel is not virtual you cannot mock it with moq.
You have two options:
Create a wrapper interface:
public interface ICancellationTokenSource
{
void Cancel();
}
and an implementation which delegates to the wrapped CancellationTokenSource
public class CancellationTokenSourceWrapper : ICancellationTokenSource
{
private readonly CancellationTokenSource source;
public CancellationTokenSourceWrapper(CancellationTokenSource source)
{
this.source = source;
}
public void Cancel()
{
source.Cancel();
}
}
And use the ICancellationTokenSource as PermanentCancellation then you can create an Mock<ICancellationTokenSource> in your tests:
// arrange
var mockCancellationTokenSource = new Mock<ICancellationTokenSource>();
viewMock.SetupGet(m => m.PermanentCancellation)
.Returns(mockCancellationTokenSource.Object)
// act
// do something
// assert
mockCancellationTokenSource.Verify(m => m.Cancel());
And use the CancellationTokenSourceWrapper in your production code.
Or use a mocking framework which supports mocking non virtual members like:
Microsoft Fakes
Typemock isolator (commercial)
JustMock (commercial)
I went a step further and made a factory to create a CancellationTokenManager class that implements the interface. This was because my method has to take CancellationToken and I wanted granular control over .IsCancellationRequested():
My CancellationTokenManagerFactory:
public interface ICancellationTokenManagerFactory
{
ICancellationTokenManager CreateManager(CancellationToken token);
}
public class CancellationTokenManagerFactory : ICancellationTokenManagerFactory
{
public ICancellationTokenManager CreateManager(CancellationToken token)
{
return new CancellationTokenManager(token);
}
}
and the manager:
public interface ICancellationTokenManager
{
bool IsCancellationRequested { get; }
CancellationToken CancellationToken { get; }
}
public class CancellationTokenManager : ICancellationTokenManager
{
private readonly CancellationToken _token;
public CancellationTokenManager(CancellationToken token)
{
_token = token;
}
public bool IsCancellationRequested
{
get
{
return _token.IsCancellationRequested;
}
}
public CancellationToken CancellationToken => _token;
}
Then in a class utilizing:
public class MyService
{
private readonly ICancellationTokenManagerFactory _factory = factory;
public MyService(ICancellationTokenManagerFactory factory)
{
_factory = factory;
}
public void StartAsync(CancellationToken token)
{
manager = _factory.CreateManager(token);
//check if cancelled
if (!manager.IsCancellationRequested())
}
// do some work
}
}
}
Now if I check cancellation is requested more than once i can mock with different responses each time. Additionally, any interfaces like IHostService can still be utilized because CancellationToken is passed in although it doesn't necessarily matter what is in that token.