Search code examples
nunitnunit-consoleparameterized-unit-test

Using the output of a [ValueSourceAttribute] Nunit Test in the following Test


I am developing a unit test project where I create an item in a test, then create sub items for it in the following test.

These tests are parameterized tests, and these parameters are collected in the runtime, so when the project starts it starts. It fails to retrieve the parent item from the database because they are not created yet "as I haven't run the first test yet".

Is there a workaround for this?

The first function:

[Test, Sequential]
public void AddInitiative([ValueSourceAttribute("Get_AddInitiatives_Data_FromExcel")]AddInitiative Initiative_Object)
{
        string URL = "http://" + Server_name + Port_number + "/IntegrationHub/IntegrationHub.svc/RestUnsecure/AddInitiative";
        string Token = Get_Security_token("gpmdev\\administrator", "Xyz7890", TenantID_Input);
        var Response = POST_Request(Initiative_Object, URL, Token);
        Guid Returned_GUID = GenericSerializer<Guid>.DeserializeFromJSON(Response);
        DataBase_Queries DB = new DataBase_Queries();
        List<StrategyItem> StrategyItemsFromDB=DB.GetStrategyItemByID(Returned_GUID.ToString());
        Assert.AreEqual(Initiative_Object.Initiative.Name_En, StrategyItemsFromDB[0].Name_En);
} 

The second function that fails:

[Test, Sequential]
public void AddInitiativeMilestones([ValueSourceAttribute("Get_AddInitiativeMilestones_Data_FromExcel")]AddMilestone Milestone_Object)
{
        string URL = "http://" + Server_name + Port_number + "/IntegrationHub/IntegrationHub.svc/RestUnsecure/AddInitiativeMilestones";
        string Token = Get_Security_token("gpmdev\\administrator", "Xyz7890", TenantID_Input);
        var Response = POST_Request(Milestone_Object, URL, Token);
        List<Milestone> Returned_Milestone = GenericSerializer<List<Milestone>>.DeserializeFromJSON(Response);
        DataBase_Queries DB = new DataBase_Queries();
        List<StrategyItem> StrategyItemsFromDB = DB.GetStrategyItemByID(Returned_Milestone[0].ID.ToString());
        Assert.AreEqual(Milestone_Object.Milestones[0].Name_En, Returned_Milestone[0].Name_En);
        Assert.AreEqual(Milestone_Object.Milestones[0].Name_En,StrategyItemsFromDB[0].Name_En);
}

Update: When I clicked from the GUI on Clear fixture the test data was reloaded, but it there a way to do that without the GUI?


Solution

  • It's generally bad practice in unit tests to have one test depend on (i.e. use output from) another test. In this case, with NUnit, it's actually impossible.

    It's impossible because NUnit creates tests long before they are executed. NUnit will call your TestCaseSource methods at what we call "load time" when NUnit decides what tests exists and populates a GUI if you use one.

    The code in your tests executes at "run time" for the tests. In a gui, this may happen multiple times for each load - every time you click Run, for example.

    Note that I'm explaining this in terms of a GUI because it's an easy way to conceptualize it. NUnit works the same way whether you are running in batch or interactively.

    If you want something to happen only once, before any tests are run, you can use OneTimeSetUp (TestFixtureSetUp in NUnit V2) to set it up. You can use a member of the class to save whatever you need from that execution and access it from your tests. However, this will still happen at "run time", decades (in computer terms) after your tests have been loaded.