I have to test a method which does a certain amount of work after an interval.
while (running)
{
...
// Work
...
Thread.Sleep(Interval);
}
Interval is passed in as a parameter to the class so I can just pass in 0 or 1 but I was interested as to how to mock the system clock if this wasn't the case.
In my test I'd like to be able to simply set the time forward by TimeSpan Interval and have the thread wake up.
I've never written tests for code which acts upon the executing thread before and I'm sure there are some pitfalls to avoid - please feel free to elaborate on what approach you use.
Thanks!
If you do not wish to test the fact that the thread actually sleeps, a more straightforward approach (and one that is possible) is to have an ISleepService. You can then mock this out, and then not sleep in your tests, but have an implementation that does cause a Thread.Sleep in your production code.
ISleepService sleepService = Container.Resolve<ISleepService>();
..
while (running)
{
...
// Work
...
sleepService.Sleep(Interval);
}
Example using Moq:
public interface ISleepService
{
void Sleep(int interval);
}
[Test]
public void Test()
{
const int Interval = 1000;
Mock<ISleepService> sleepService = new Mock<ISleepService>();
sleepService.Setup(s => s.Sleep(It.IsAny<int>()));
_container.RegisterInstance(sleepService.Object);
SomeClass someClass = _container.Resolve<SomeClass>();
someClass.DoSomething(interval: Interval);
//Do some asserting.
//Optionally assert that sleep service was called
sleepService.Verify(s => s.Sleep(Interval));
}
private class SomeClass
{
private readonly ISleepService _sleepService;
public SomeClass(IUnityContainer container)
{
_sleepService = container.Resolve<ISleepService>();
}
public void DoSomething(int interval)
{
while (true)
{
_sleepService.Sleep(interval);
break;
}
}
}
Update
On a design\maintenance note, if it is painful to change the constructor of "SomeClass", or to add Dependency Injection points to the user of the class, then a service locator type pattern can help out here, e.g.:
private class SomeClass
{
private readonly ISleepService _sleepService;
public SomeClass()
{
_sleepService = ServiceLocator.Container.Resolve<ISleepService>();
}
public void DoSomething(int interval)
{
while (true)
{
_sleepService.Sleep(interval);
break;
}
}
}
You can't really mock the system clock.
If you need to be able to alter the suspend behavior of code like this, you will need to refactor it so that you are not calling Thread.Sleep() directly.
I would create a singleton service, which could be injected into the application when it's under test. The singleton service would have to include methods to allow some external caller (like a unit test) to be able to cancel a sleep operation.
Alternatively, you could use a Mutex or WaitHandle object's WaitOne() method which has a timeout parameter. This way you could trigger the mutex to cancel the "sleep" or let it timeout:
public WaitHandle CancellableSleep = new WaitHandle(); // publicly available
// in your code under test use this instead of Thread.Sleep()...
while( running ) {
// .. work ..
CancellableSleep.WaitOne( Interval ); // suspends thread for Interval timeout
}
// external code can cancel the sleep by doing:
CancellableSleep.Set(); // trigger the handle...
Related
I have a class wich performs some data processing:
class Processor
{
public Processor() {
// Load lot of data
}
public string GetResult(string input) {
// ...
}
}
I need to implement a service wich exposes HTTP API to this class. I use Owin and Microsoft.AspNet.* libs to host HTTP Web API. For each request it creates a new thread to handle it, but I cannot instantiate Processor on every request as it takes enormous time to load some data in its constructor. Also I cannot reuse one instance from different threads as it was not designed to be thread safe. But I can instantiate several instances of Processor on service start, and then dispatch work among them. Say I allow up to 20 concurrent HTTP requests for my service. I create 20 instances of Processor and add Busy flag to the class:
class Processor
{
public bool Busy { get; set; }
// ...
}
I wrote Dispatcher class like this:
class Dispatcher
{
readonly Processor[] _processors;
readonly SemaphoreSlim _semaphore;
public Dispatcher(int maxProcessors)
{
_semaphore = new SemaphoreSlim(maxProcessors);
_processors = new Processor[maxProcessors];
// Instantiate Processors, etc...
}
public string GetResult(string input)
{
try
{
_semaphore.Wait(); // Surplus requests will wait here.
Processor processor;
lock (_processors)
{
// It is guaranteed that such processor exists if we entered the semaphore.
processor = _processors.First(p => !p.Busy);
processor.Busy = true;
}
var result = processor.GetResult(input);
processor.Busy = false;
return result;
}
finally
{
_semaphore.Release();
}
}
}
Then I can basically call it through Dispatcher in ApiController:
public class ServiceController : ApiController
{
static Dispatcher _dispatcher = new Dispatcher(20);
[Route("result")]
[HttpGet]
public string Result(string input)
{
return _dispatcher.GetResult(input);
}
}
Is it implemented correctly for my purpose?
I tested it and it works, but I wonder if I reinvented the wheel and .NET Framework has somewhat ready to use for my case, or if it could be implemented easier.
Basically in your class that is going to be run in the thread, create an event and event handler. The object that then spins up this task can register to that event. When it is raised by the task, (in this case you would raise the event when it is done) you can do something, ie. give it more work.
Create your events in the class that will be run in the child thread:
public event TaskCompleteEventHandler OnComplete;
public event TaskErrorEventHandler OnError;
Register to your events in the object that is spinning up the classes:
task.OnComplete += TaskComplete;
task.OnError += TaskComplete;
Create the function in the calling class that will handle the event:
public void TaskComplete()
{
//give the thread more work
}
My program is a simple timer (it's a Pomodoro Timer). I'm trying to incorporate unit testing into my personal projects.
I run my tests on each timer class' run() method and assert that the endTime - startTime is within 1 second of how long I set the timer.
MyTimer.run() invokes Thread.sleep(timerMilliseconds).
My unit tests pass in less time than each timer is set for.
How is this possible?
Eg. Rest is set to 5 seconds, unit test passes in < 1ms
[TestMethod]
public void testRun () {
TimeSpan fiveSeconds = new TimeSpan(5000);
Rest rest = new Rest(fiveSeconds, null);
TimeSpan startTime = DateTime.Now.TimeOfDay;
try {
rest.run();
}
catch (Exception e) {
Assert.Fail(e.ToString());
}
Assert.AreEqual(startTime.Add(fiveSeconds).TotalMilliseconds, DateTime.Now.TimeOfDay.TotalMilliseconds, 1000 , "Actual sleep time not expected");
}
public class Rest : Session {
private TimeSpan timeSpan;
public override void run () {
Thread.Sleep(base.getTimer().Milliseconds); **//SOLVED: SHOULD READ base.getTimer().TotalMilliseconds**
}
public Rest (TimeSpan timeSpan, Cycle cycle) : base(timeSpan, cycle) {
this.timeSpan = timeSpan;
}
}
public abstract class Session {
private readonly TimeSpan timer;
protected Cycle cycle;
public TimeSpan getTimer () {
return this.Timer;
}
protected Session (TimeSpan minutes, Cycle cycle) {
this.timer = minutes;
this.cycle = cycle;
}
public abstract void run ();
}
The basic problem is this:
public override void run () {
Thread.Sleep(base.getTimer().Milliseconds);
}
You want to sleep for TotalMilliseconds, not Milliseconds (the Milliseconds component of the TimeSpan - 0 in this case).
That said, speaking more broadly, you just don't want to unit test a method that calls Thread.Sleep, especially not to test the duration of the call. That test will take a long time, be brittle and approximative; 3 properties you absolutely want to avoid in unit tests. To make this code testable, you'd need to abstract the call to Thread.Sleep behind some interface that you can then mock in your unit tests (see dependency injection). Your unit test could have then verified that the value passed to Sleep() was what you expected, and you would have caught this bug without all the problems that testing a real call to Thread.Sleep will cause.
I have a single thread VB.net service that checks a database for specific information. If the info does not exist, it needs to wait 15 minutes and try again. What is the best method to have the service wait during this 15 minute period? I considered a Do loop with threading.thread.sleep, but am always reading how that is bad to use, but I do not know an alternative. Any suggestions of a better method for this would be appreciated.
I guess you may, alternatively to Thread.Sleep:
1 - Make your application as SINGLE INSTANCE (see the Properties of your Solution).
2- Add an Schedule Event into Task Scheduler of the Windows to call your application on each 15 minutes.
3- Your program will be terminated normally and will be called from Windows (or manually by user).
4- Since Single-Event you won´t have many instances of the application running at the same time - just one. So, even if the Task Scheduler starts a new instance, you may be sure that just one instance will be running.
Using a BackgroundWorker and a ManualResetEvent I think you can do what you have in mind.
public class LibraryBackgroundTimer : BackgroundWorker
{
private ManualResetEvent intervalManualReset;
public int Interval { get; set; }
public LibraryBackgroundTimer()
{
this.WorkerSupportsCancellation = true;
this.Interval = 1000;
}
protected override void OnDoWork(DoWorkEventArgs e)
{
while (!this.CancellationPending)
{
base.OnDoWork(e);
this.Sleep();
}
}
public void Start()
{
if (this.IsBusy)
return;
this.intervalManualReset = new ManualResetEvent(false);
this.RunWorkerAsync();
}
public void Stop()
{
this.CancelAsync();
this.WakeUp();
this.Dispose(true);
}
public void WakeUp()
{
if (this.intervalManualReset != null)
this.intervalManualReset.Set();
}
private void Sleep()
{
if (this.intervalManualReset != null)
{
this.intervalManualReset.Reset();
this.intervalManualReset.WaitOne(this.Interval);
}
}
}
using this class your timer can be stopped for a desired time and also it's capable of being waked up during the sleep time.
I hope this helps.
I'm trying to implement fire and forget functionality, using the Task Parallel Library. With an inline call to Task.Factory.StartNew, everything works as expected. However, I want to move the Task.Factory.StartNew call into a separate class so that I can add logging, error handling, etc, and potentially upgrade the code in the future as better threading classes, etc are added to the .NET Framework, without duplicating code.
Below is a unit test that I would expect to pass, but that does not. I would appreciate help trying to figure out how to make this work.
[TestFixture]
public class ThreadingServiceFixture
{
public static bool methodFired = false;
[Test]
public void CanFireAndForgetWithThreadingService()
{
try
{
var service = new ThreadingService();
service.FireAndForget(() => methodFired = true);
var endTime = DateTime.Now.AddSeconds(1);
while(DateTime.Now < endTime)
{
//wait
}
Assert.IsTrue(methodFired == true);
}
finally
{
methodFired = false;
}
}
}
public class ThreadingService
{
public Task FireAndForget(Action action)
{
return Task.Factory.StartNew(() => action);
}
}
You're not executing the action, you're just returning it.
Try:
return Task.Factory.StartNew(() => action());
If is "fire and forget" you don't need to return the Task from the FireAndForget method, because the caller could get that Task and cancel it (strictly speaking the caller would "remember" of the call).
If you want to invoke this method from many services that do not inherit from a common ThreadingService you can implement an extension method via an interface.
public interface IFireAndForget
{
// no member needed.
}
public static class FireAndForgetExtensions
{
public static void FireAndForget(this IFireAndForget obj, Action action)
{
// pass the action, not a new lambda
Task.Factory.StartNew(action);
}
}
// using
public class ThreadingService : IFireAndForget
{
}
Also note the in your method you have to pass the action to the StartNew method insted of pass a lambda that return the action parameter.
You did not invoke the action in the ThreadingService
The code should read something like
public class ThreadingService
{
public Task FireAndForget(Action action)
{
return Task.Factory.StartNew(() => action.Invoke());
}
}
Additional note: testing state with a public field is evil. Think about repeatability, maintenance, running tests in different order. You should move bool methodFired inside the test. I would also assume there is a better technique to test this (but I am not sure which one).
Testing threaded code is hard.
Basing your tests on timing is a bad idea, they may become non-deterministic and you might observe erratic behavior on you build server. Imagine a tests that sometime passes and sometimes doesn't!
Your code has a bug, since you are not actually invoking the action.
But consider this variation:
[Test]
[TimeOut(5000)]
public void CanFireAndForgetWithThreadingService()
{
var service = new ThreadingService();
ManualResetEvent mre = new ManualRestEvent(bool); // I never remember what is the default...
service.FireAndForget(() => mre.Set() /*will release the test asynchroneously*/);
mre.WaitOne(); // blocks, will timeout if FireAndForget does not fire the action.
}
Yes, we are still using timing. But the test the timeout will happen only if the code breaks!
In all other scenarios, the test is absolutely predictable and takes a very short amount of time to execute, no waiting and praying for timing issues not to happen ;-)
I have a DispatcherTimer and I check for the busy/free status of a component in the timer tick of this timer. I have to wait till the component becomes free, something like IsBusy() method returns false, and then I have to automatically start something. I want to test the scenario by first simulating the component to be busy and then make it free after some time and see that the automatic function starts. Of course, once I invoke the code under test, I enter a wait. Is it possible to set fresh expectations from test and send an update to the production code so that I can do what I need to do? I am using Nunit for unit tests.
You can use the Rhino Mocks' Do() Handler to simulate a pre-specified wait time in the IsBusy() method of the component being mocked:
[TestFixture]
public class TestClass
{
[Test]
public void MyTest()
{
var mocks = new MockRepository();
var mockComponent = mocks.DynamicMock<MyComponent>();
using (mocks.Record ())
{
Expect.Call(() => mockComponent.IsBusy())
.Do((Func<bool>)(() =>
{
System.Threading.Thread.Sleep(10000); // wait 10 seconds
return false;
}));
// perhaps define other expectations or asserts here...
}
using (mocks.Playback())
{
var classUnderTest = new ClassUnderTest(mockComponent);
classUnderTest.MethodUnderTest();
}
mocks.VerifyAll();
}
}
You can then test different Sleep times as needed via multiple unit tests or using NUnit's Parameterized Tests (I just arbitrarily chose to wait 10 seconds).
The ClassUnderTest.MethodUnderTest() should be calling MyComponent.IsBusy() at some point in its implementation either directly or perhaps indirectly via the Tick event handler of the DispatcherTimer you mentioned. Without seeing your code, my guess is that you might have something similar to this:
public class ClassUnderTest
{
private MyComponent myComponent;
public ClassUnderTest(MyComponent myComponent)
{
this.myComponent = myComponent;
}
public void MethodUnderTest()
{
dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0,0,1);
dispatcherTimer.Start();
// ...
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
if(!myComponent.IsBusy())
{
// do something else now...
}
}
}
public class MyComponent
{
public virtual bool IsBusy()
{
// some implementation that will be faked via the Do Handler
return false;
}
}
Your expectations can be dynamically created, but they should be set up in one place, rather than "interactively". You shouldn't try to change them while in the middle of exercising your code-under-test.
To accomplish your goal, you could try using the Repeat option to allow the check to loop a certain number of times:
mock.Expect(theMock => theMock.IsBusy())
.Return(true)
.Repeat.Times(5);
mock.Expect(theMock => theMock.IsBusy())
.Return(false);