1
\$\begingroup\$

In Unity how can I unit test the start method?

I am not trying to test interaction between objects but the private methods are called by the Start method, so I figured I should call the start method and check the values of the object. But it seems the Start method is not called at all.

To make sure it is not some bug in my actual code that is being tested I added this line to the Start method of the building class: numberOfXTiles+=23432

I have a Scene called "TestScene" that I add an empty GameObject called "TestObject"

TestScene

This is the play mode testing script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.TestTools;
using NUnit.Framework;
using UnityEngine.SceneManagement;
using System;

public class TestBuilding
{

// A reference to the game object that has the script with the Start method
private GameObject gameObject;
private Building building;

// A method that runs before each test and instantiates the game object
[UnitySetUp]
public IEnumerator SetUp()
{
    // Load the scene asynchronously
    SceneManager.LoadScene("TestScene");

    // Wait until the scene is loaded
    yield return new WaitUntil(() => SceneManager.GetSceneByName("TestScene").isLoaded);
    
    gameObject = GameObject.Find("TestObject");
   
    gameObject.AddComponent<Building>();
    building = gameObject.GetComponent<Building>();
    yield return null;
}

[UnityTest]
public IEnumerator TestTileNumberAutoCalculation()
{
    //setting up
    building.numberOfXTiles = 2;
    building.numberOfZTiles = 3;
    building.occupiedTilesRelativeGridVectors.Add(new Vector3(12, 0, 9));

    //expecteds
    int expectedX = 12, expectedZ = 9;

    yield return null;//wait one turn so that start method is run

    bool xPassed, zPassed;

    //checks
    xPassed = (expectedX == building.numberOfXTiles);
    zPassed = (expectedZ == building.numberOfZTiles);

    //handle message
    string message = "";
    if (!xPassed)
    {
        message += "X failed to pass: expected =  " + expectedX + "  found = " + building.numberOfXTiles + "\n";
    }
    if (!zPassed)
    {
        message += "Z failed to pass: expected = " + expectedZ + "  found = " + building.numberOfZTiles;
    }

    Assert.IsTrue(xPassed && zPassed, message);
}
}

Console output says x is 2. That is how I am sure Start method is not run. However if I add the same line to the update I see that x has changed to 23432.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I figured it out. gameObject.setActive(bool) is the solution.

I believe the start method is being called when the MonoBehaviour object is added as the component in this line gameObject.AddComponent<Building>(); So what is happening is the start method is triggering and doing its thing in the [UnitySetUp] method then I am setting the values I need in the actual test method. And since the start method is already fired the new values are not being processed.

To solve this issue, I set the gameObject as inactive before adding the component in the setup and I turn it active after I set the values.

[UnitySetUp]
public IEnumerator SetUp()
{
    SceneManager.LoadScene("TestScene");

    // Wait until the scene is loaded
    yield return new WaitUntil(() => SceneManager.GetSceneByName("TestScene").isLoaded);
    
    gameObject = GameObject.Find("TestObject");
   gameObject.SetActive(false);
    gameObject.AddComponent<Building>();
    building = gameObject.GetComponent<Building>();
   
}

[UnityTest]
public IEnumerator TestTileNumberAutoCalculation()
{

    //setting up
    building.numberOfXTiles = 2;
    building.numberOfZTiles = 3;

    building.occupiedTilesRelativeGridVectors.Add(new Vector3(12, 0, 9));

    gameObject.SetActive(true);
   ...

I am setting it as a community wiki so that people can correct any bad practice and write the perfect unit test method.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .