5

This is a very basic question but I still cannot find the appropriate answer. In my test there is a possibility to have null values and because of that the last stage (Act) starts looking a little bit strange (it is no longer act only). What I mean is the following:

Assert.IsNotNull(variable);

var newVariable = variable.Property;
Assert.IsNotNull(newVariable);

var finalVariable = newVariable.AnotherProperty;
Assert.AreEqual(3, finalVariable.Count);

Now they are obviously related and I have to be sure that the values are not null, but also there are three asserts in one test and the act part starts to look not right.

So what is the general solution in such cases? Is there anything smarter than 3 tests with one assert each and checks for null before the asserts of the last 2?

4 Answers4

1

Basically there are two ways of dealing with your problem:

  1. Guard assertions: extra asserts making sure data is in known state before proper test takes place (that's what you're doing now).
  2. Moving guard assertions to their own tests.

Which option to chose largely depends on code under test. If preconditions would be duplicated in other tests, it's a hint for separate test approach. If precondition has reflection in production code, it's again hint for separate test approach.

On the other hand, if it's only something you do to boost your confidence, maybe separate test is too much (yet as noted in other answers, it might be a sign that you're not in full control of your test or that you're testing too many things at once).

Community
  • 1
  • 1
k.m
  • 30,794
  • 10
  • 62
  • 86
0

I think you should split this test into three tests and name them accordingly to what's happening. It's perfectly sensible even if your acts in those tests are same, you are testing different scenarios by checking return value of the method.

Ufuk Hacıoğulları
  • 37,978
  • 12
  • 114
  • 156
0

Nulls are royal pain. The question is, can they legitimately exist?

Let's separate our discussion to code and tests.

If the null shouldn't exist then the code itself, not the tests, should check and verify that they are not null. For this reason each and every method of my code is built using a snippet that checks the arguments:

    public VideoPosition(FrameRate theFrameRate, TimeSpan theAirTime)
    {

        Logger.LogMethod("theVideoMovie", theFrameRate, "theAirTime", theAirTime);
        try
        {
            #region VerifyInputs

            Validator.Verify(theFrameRate);
            Validator.Verify(theAirTime);
            Validator.VerifyTrue(theAirTime.Ticks >= 0, "theAirTime.Ticks >= 0");

If null ARE legitimate in the code, but you are testing a scenario where the returned values shouldn't be null, then of course you have to verify this in your testing code.

Avi
  • 15,696
  • 9
  • 39
  • 54
0

In your Unit Test you should be able to control every input to your class under test. This means that you control if your variable has a value or not.

So you would have one unit test that forces your variable to be null andnthen asserts this.

You will then have another test where you can be sure that your variable has a value and you omly need the other asserts.

I wrote a blog about this some time ago. Maybe it can help: Unit Testing, hell or heaven?

Wouter de Kort
  • 39,090
  • 12
  • 84
  • 103