testing method which create a new thread and result we get from event ( NUnit 2.6 )

后端 未结 4 643
别那么骄傲
别那么骄傲 2021-02-10 01:26

I have class which have one public method Start, one private method and one event Finishing. Start call new Thread( private_method )

相关标签:
4条回答
  • 2021-02-10 01:28

    As mentioned you can unit test multi threaded components but it is not clean like regular unit tests. I have mostly encountered it in Acceptance Tests and have had great success with the .net 4 Task and Parallel classes. However in this case a simple sleep might get you going but if you start doing lots of these tests you might want a more performant way of doing it.

    [Test]
    public void Test1()
    {
        bool wasCalled = false;
    
        SomeClass someObject = new SomeClass();
    
        someObject.Finishing += new SomeClass.FinishingEventHandler((sender, a) =>
        {
            wasCalled = true;
        });
        someObject.Start(); // when this method will finish, then call event Finishing
    
        Thread.Sleep(2000);
    
        Assert.True(wasCalled);
    }
    

    What ever you do you need some timeout somewhere that will cause the test to finish instead of hanging forever, this could be done in the test itself or some test libraries have a Timeout attribute you can decorate the test with.

    0 讨论(0)
  • 2021-02-10 01:39

    You are right.

    First of all, NUnit and its various hosting environments had, or still have, various defects and limitations around threads started from within a test. In particular, if you do not make sure that the thread completes before the test execution is finished, then NUnit has no idea that someone is executing in code that it is going to unload after the test has returned. I remember this pattern regularly causing crashes of VS when NUnit was being executed from it via Resharper integration, as well as occasional glitches and memory leaks of the GUI and console runners provided with NUnit.

    That said, you need to ensure two things.

    1. Elementary safety of the test environment by joining all the threads that you spawn.
    2. Throwing all exceptions that indicate test failure on the main thread only. This means that the background thread has to communicate its results to the main thread, and that one has to Assert all the various invariants.

    Even better, structure your code so that you can unit test it without background threads - if possible.

    0 讨论(0)
  • 2021-02-10 01:43

    NUnit has built-in feature for waiting for assertion. It is called 'After':

    [Test]
    public void ShouldRaiseFinishedEvent()
    {
        SomeClass someObject = new SomeClass();
        bool eventRaised = false;
        someObject.SomethingFinished += (o, e) => { eventRaised = true; };
    
        someObject.DoSomething();
        Assert.That(eventRaised, Is.True.After(500));
    }
    
    0 讨论(0)
  • 2021-02-10 01:45
    [Test]
    public void ShouldRaiseFinishedEvent()
    {
        SomeClass someObject = new SomeClass();
        AutoResetEvent eventRaised = new AutoResetEvent(false);
        someObject.SomethingFinished += (o, e) => { eventRaised.Set(); };
    
        someObject.DoSomething();
        Assert.IsTrue(eventRaised.WaitOne(TimeSpan.FromMilliseconds(500)));
    }
    

    This should work

    0 讨论(0)
提交回复
热议问题