fafase
fafase

Reputation: 477

NUnit TestCaseSource null on first run

Using NUnit and Unity I have a base class for tests:

    [TestFixture]
    public class TestBase
    {
        private string m_filePath = "UnitTest\\response.json";

        protected static Event m_current;
        protected static Event m_expired;

        protected LoginResponse m_response;

        public static IEnumerable<TestCaseData> TestRunning
        {
            get
            {
                yield return new TestCaseData(m_expired, false);
                yield return new TestCaseData(m_current, true);
            }
        }

        [OneTimeSetUp]
        public virtual void SetUp()
        {
            string path = System.IO.Path.Combine(Application.dataPath, m_filePath);
            string txt = File.ReadAllText(path);
            m_response = JsonFx.Json.JsonReader.Deserialize<LoginResponse>(txt);

            m_expired = m_response.events[0];
            m_current = m_response.events[1];
        }

        protected class LoginResponse
        {
            public List<Event> events;
        }
    }

I then have a TestCaseSource in a sub class that uses the TestRunning collection and it will fail on first run of the tests after recompiling. If I run the tests again, they pass. The first object comes null in the tests.

The sub class does not have a Setup so it is not preventing the call.

Upvotes: 1

Views: 397

Answers (2)

fafase
fafase

Reputation: 477

Based on @Charlie's answer, here the needed modifications that solved my issue:

public class TestBase
{
    private string m_filePath = "UnitTest\\response.json";

    protected static Event m_current;
    protected static Event m_expired;

    protected static LoginResponse m_response;

    public static IEnumerable<TestCaseData> TestRunning
    {
        get
        {
            if(m_response == null)
            {
                SetUpTest();
            }
            yield return new TestCaseData(m_expired, false);
            yield return new TestCaseData(m_current, true);
        }
    }

    [OneTimeSetUp]
    public virtual void SetUp()
    {
        SetUpTest();
    }

    protected class LoginResponse
    {
        public List<Event> events;
    }
    
    private static void SetUpTest()
    {
        string path = System.IO.Path.Combine(Application.dataPath, m_filePath);
        string txt = File.ReadAllText(path);
        m_response = JsonFx.Json.JsonReader.Deserialize<LoginResponse>(txt);

        m_expired = m_response.events[0];
        m_current = m_response.events[1];
    }
}

Upvotes: 0

Charlie
Charlie

Reputation: 13736

There are various ways to explain the order in which NUnit performs various actions on tests, with different levels of detail. Here is the highest level possible...

  1. All actions having to do with discovering tests. This includes finding and interpreting all the attributes, which provide data, including [TestCase], [TestCaseSource], [Values], etc.

  2. All actions having to do with executing the tests that were discovered. This includes executing all OneTimeSetup and SetUp methods, the test methods themselves, and any TearDown and OneTimeTearDown methods.

Within group 2, there are fairly complicated rules about which specific actions are taken first, but even the earliest actions (such as a base class OneTimeSetUp method) will never be taken before the actions in group 1 are complete.

The reason for this strict ordering is that the attributes in group 1 do not merely provide data for the running tests to use. They also determine how many tests are found. That is, a TestCaseSource with five sets of values, creates five tests, one with 100 sets creates 100 tests.

Once you understand this, the solution is easy enough. Your TestCaseSource must actually read the json file and create cases based on what is found there. This means your source will probably need to be a method rather than a simple collection.

Upvotes: 2

Related Questions