← Back to team overview

nunit-core team mailing list archive

[Bug 893919] Re: DelayedConstraint fails polling properties on references which are initially null

 

Thanks for the quick response.

I think your 'null test' example certainly makes good sense. I'm writing tests to check whether an event handler is called with the correct arguments from another thread within a specific time.
In some cases I also want to make sure it's *not* called, in which case the handler arguments should remain null - so I have plenty of Is.Null.After(...) tests too.

So the behaviour of that should not change. However, in the example I
gave earlier, the problem isn't the object being null/not null, it's
that polling properties of the object will always fail on the first poll
in the case where the object is null.

Further similar problems can be found using the following examples:
    Assert.That(() => statusString.Length, Is.GreaterThan(0).After(3000, 100));
    Assert.That(() => statusString, Has.Property("Length").GreaterThan(0).After(3000, 100));

This problem has also lead to timing issues where the test passes if the
event which initialises the object occurs early enough, otherwise it
will fail (I only found the problem when I ran all the tests in the
fixture, rather than each test individually).

Your suggestion of catching and ignoring the null reference exception
seems like the right solution to me.

However, I thought of a case where this may lead to a problem where exceptions are expected after a delay, eg:
    Assert.That(() => statusString.Count, Throws.TypeOf<NullReferenceException>.After(3000, 100));

Perhaps the null reference exception should only be thrown when using a
'Throws' constraint?

(Apologies for syntax errors etc, I don't have access to Visual Studio
presently)

-- 
You received this bug notification because you are a member of NUnit
Developers, which is subscribed to NUnit V2.
https://bugs.launchpad.net/bugs/893919

Title:
  DelayedConstraint fails polling properties on references which are
  initially null

Status in NUnit V2 Test Framework:
  Triaged

Bug description:
  Having seen the great progress made on bug #890129, I've been using the After() constraint even more!
  (Still using v2.5.10.11092)

  I noticed a quirk with how (properties of) objects which are initially
  null are polled.

  An example:
      string statusString = null; // object starts off as null

      var worker = new BackgroundWorker();
      worker.RunWorkerCompleted += delegate { statusString = "finished"; /* object non-null after work */ };
      worker.DoWork += delegate { Thread.Sleep(TimeSpan.FromSeconds(1)); /* simulate work */ };
      worker.RunWorkerAsync();
           
      Assert.That(() => statusString, Has.Length.GreaterThan(0).After(3000, 100));

  The assert will fail after its first poll, reporting:
           System.ArgumentNullException : Value cannot be null.
           Parameter name: actual

  I assume this is because the 'statusString' object is null, so fetching the 'Length' property causes a ArgumentNullException.
  However, I'd expect that the test would at least continue to try to poll even if the value is initially null, in case it gets initialised before the timeout.

  A few simple workarounds exist:

  Adding a prior null check to the constraint:
      Assert.That(() => statusString, Is.Not.Null.With.Length.GreaterThan(0).After(3000, 100));

  Or adding another separate DelayedConstraint before the Assert which checks for non-null, like this:
      Assert.That(() => statusString, Is.Not.Null.After(3000, 100));
      Assert.That(() => statusString, Has.Length.GreaterThan(0).After(3000, 100));

  Perhaps that is because each constraint must pass or timeout before
  the next is run. The documentation doesn't specify whether each
  'After' assert is run on a separate thread or whether earlier ones
  block.

To manage notifications about this bug go to:
https://bugs.launchpad.net/nunitv2/+bug/893919/+subscriptions


References