How can I unit test the lock statement?

How to write unit test to make sure that a lock has been received?

For example:

public void AddItem(object item) { lock (_list) { _list.Add(item) } } 

Is there any way to make sure the lock statement is running?

Change I am not trying to prove thread safety (I would assume that), the lock () statement is just called.

For example, I can test the new object() operator by replacing it in the CreateObject() factory function.

+7
source share
6 answers

Similarly, you test any other thing: write a test that will fail without it. In other words, determine why you record the lock in the first place, and write a test that indicates this reason. I guess the reason is thread safety: if so, write a multi-threaded test. If this is some other reason, the test is right.

If you really want to test the lock call, but not the behavior that causes the lock, encapsulate:

 public class MyLock : IDisposable { private object _toLock; public MyLock(object toLock) { _toLock = toLock; Monitor.Enter(_toLock); } public virtual void Dispose() { Monitor.Exit(_toLock); } } 

Of course, you also have to do a factory layout. It seems to be overdoing it, but maybe it makes sense in your context.

+4
source

Group testing of multiple threads is always difficult and should be handled with care.

In your case, I would not test the lock keyword, for the same reason you are not writing tests for new .

Assert.IsNotNull(new object());

Also, you seem to be encapsulating as an insecure collection to make it thread safe. Instead of reinventing the wheel, consider thread-safe collections .

+8
source

See Jon Skeet's answer to a similar question: How to check if a thread supports object lock in C #? :

I do not believe that there is. There are cumbersome things you could do like calling Monitor.Wait (monitor, 0) and catching a SynchronizationLockException, but this is pretty awful (and could theoretically β€œcatch” the pulse expected by another thread).

+2
source

If you wrote the Lock statement (something similar to the System.Threading.Lock statement), I can understand why you want to test it.

In this case, you need to have the _list class that you have implemented the .Add method for this class, it will be much easier if you use dependency injection to insert IList to set _list. You will need to use a dummy instance of IList that implements the .Add () method.

If you have dummy.Add () cause hibernation for a given period of time (for example, 5 seconds), you can test by running a thread to call the .AddItem () method, this thread will block .Add () through the .AddItem ( ), the main thread can then wait 3 seconds before calling the .AddItem method.

If the lock works, the second thread is delayed for 2 seconds before executing .Add, if the lock does not work, it will immediately ring.

This is random and non-deterministic, so if you run enough time (millions), you will get a false result.

+1
source

You need a small program in which you emulate reading and writing using streams ...

In a new thread, create 10,000 elements and add them, while in another thread reading and then sleeping for a while.

Then, in the main waiting for both threads to exit, and you should get the results according to the number of times that the call caused and did not cause the deletion ...

For example, when i% 2 == 0, then delete instead of adding the producer to the flows ... this should also affect the consumer flow ...

see How to wait for a thread to finish with .NET?

0
source

Not sure if the module checking the lock is the right approach; rather, you should check the AddItem functions for AddItem . A couple of things you could do, however:

1) Use reflection to get a link to _list , block it in your test and try calling AddItem

2) Add an internal method to test the _list lock and pause for a reasonable amount of time (2 seconds?). If you make your insides visible for your test build , you can call the test method in one thread and call AddItem on the other. Keep in mind that this is not flawless, as technically the test may be blocked for some reason long enough for the original lock to expire.

0
source

All Articles