Not sure how to achieve this. I'm trying to unit test a method which waits a few minutes, see here:
This is my test method but I can't manage to mock the task delay stuff.
This is the error raised:
Thread sleep doesn’t lose any monitors or locks current thread has acquired. Any other thread can interrupt the current thread in sleep, in that case InterruptedException is thrown. How Thread Sleep Works. Thread.sleep interacts with the thread scheduler to put the current thread in wait state for specified period of time.
Moq.MockException : Expected invocation on the mock at least once, but was never performed: x => x.Publish(It.Is(y => y.Imei .imei)) No setups configured. No invocations performed. at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable1 setups, IEnumerable
1 actualCalls, Expression expression, Times times, Int32 callCount) at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times) at Moq.Mock.Verify[T](Mock1 mock, Expression
1 expression, Times times, String failMessage) at Moq.Mock1.Verify(Expression
1 expression) at JustEat.PrivateAPN.Worker.UnitTests.TestRunners.JctRestartViaSmsAttemptTestFixture.RunJctTest_WhenRestartAttemptSmsIsSent_ShouldPublishJctRestartValidateMessageWithTheRightImei() in
I know I need to customize/configure my fixture in order to get into the callback but I'm not sure how to do it, any help would be very appreciated
- Process orientated - few, long running, heterogeneous tasks, often event based (waiting on notification), or polling (sleeping between cycles), often expressed using a thread or runnable. Testing either type of code can be hard; the work is done in another thread, and therefore notification of completion can be opaque, or is hidden behind a level of abstraction.
- 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.
3 Answers
You shouldn't be firing a Task
off without await
ing for it to finish when your test and other things may rely on the result.
So I suggest you change to:
Another reason for await
ing is that you have this _queues
if you intend to read from that later on, you can never guarantee the contents because there may still be a thread in the threadpool processing the Task.Delay
.
Alternative
If you can't change the signature of the method then you will have to go with the Thread.Sleep()
which will block the current thread until it has finished.
Because you did specify Task.Delay
I would assume you are using it for the benefits of non blocking.
If you were to use Thread.Sleep()
you may want to consider running the JctRestartViaSmsAttemptTestRunner
in a Task.Run()
so that is will only block the thread it is running on.
Tests
If you have a method that does return Task<>
then you will have to use .Result
if you can't have async
test method signatures. Which shouldn't be an issue if you run all your tests in serial. If you don't know why .Result
and .Wait()
are bad read here
So for your async version:
And your non async version stays the same.
Callum LiningtonCallum LiningtonI think the problem is the test is allowed to finish. Your creating a new task after the delay to start but the test function itself completes before this.
I am not overly familiar with the testing framework. But I would expect you want to use .Wait() on the end of the task. This will create a blocking task and your main test thread will be blocked until the delay is finished.
The execute method is not realy testable, because it starts a delayed task, but you are not able to manage that task from outside.
So, you could try to work with Thread.Sleep
which is not nice but should work:
Not the answer you're looking for? Browse other questions tagged c#moqautofixture or ask your own question.
Disclaimer:C++ Thread Sleep
This post is based on the C# 5.0 CTP. Everything described here is subject to future changes.Last time I demonstrated that the synchronization context is also relevant for unit testing and that you might need to setup one in your tests. This time we’re going to explore what we can do when a asynchronous method returns void instead of a task.
Once again we write some code for our imaginary desktop application. This time we test a method which sends some stuff to costumers. When the package is sent an event is raised. First the synchronous version. It’s straight forward, we package the goods and then send it. When we’re done we fire the event.
The Implementation
The Test
As expected everything runs smooth. Now we’re turning the method into an asynchronous implementation
As soon as we try to update the test-method we’re facing a problem. We cannot wait for a void-result. This means there’s no way to wait for the completion of the task. Well the easiest thing to do is to change the result to return a task. This allows us to wait in the test.
Returning a Task
C Thread Sleep In Linux
The Test
In The Case Of Void
Now we’ve seen that when we return a task instead of void we can make our testing-life much easier. But what if that’s not possible? For example because we don’t want to break the API. Or if it’s a library call which we cannot change. Then this gets a little more tricky. When the method returns void we cannot wait for the task to complete. A ugly work around would be to just use Thread.Sleep for a certain time an hope that everything completes meanwhile. However this is a brittle method and prolongs our test unnecessary. What can we do instead? Remember the previous post where we used a special synchronization-context which allowed us to wait on a task? Well does this really have to be a task? I mean we can wait for other things, right?
So the basic idea is to extend our test synchronization context to provide a special wait-method. And while we’re waiting we process other messages. This is actually only a small extension to our existing code
Now we can use this in our test. We run our test-code in the test synchronization context. Then we wait until the condition is fulfilled and finally continue
You’ve probably noticed that this test will run forever instead of failing. Unfortunately we cannot fix that. The only thing we can do is to implement some kind of timeout and maybe use a reasonable default. But you can implement that without my help ;).
Unit Test Quizlet
Conclusion
In this post I demonstrated that you should always return a task in an asynchronous API instead of void. This allows us to easily test the code and makes it more flexible. In the cases where we have to deal with asynchronous code which doesn’t return a task we have to get creative with special wait conditions.
Now I’ve finished with my little tour through Unit testing with the new asynchronous features. This post series is by no means a complete guide. It’s here to get an impression where the difficulties lie. I think when the async feature ships some knowledge and patterns have already emerged. And maybe we all should take a looks at F#. Because F# has had asynchronous workflows for quite a while. And don’t forget do download and experiment with the Async CTP yourself.