2

I am using the Unity Test Tools framework. My unit test code looks like this (More included)

[TestFixture]
public class ActionMasterTester: MonoBehaviour{
    private ActionMaster actionMaster;

    [SetUp]
    public void SetUp()
    {
        actionMaster = new ActionMaster();
    }
}

The ActionMaster looks like this:

public class ActionMaster : MonoBehaviour {
}

If I run a test, then I get the following warning on the like actionMaster = new ActionMaster();

You are trying to create a MonoBehaviour using the 'new' keyword.  This is not allowed.  MonoBehaviours can only be added using AddComponent().  Alternatively, your script can inherit from ScriptableObject or no base class at all
UnityEngine.MonoBehaviour:.ctor()
ActionMaster:.ctor()
ActionMasterTester:SetUp() (at Assets/Editor/ActionMasterTester.cs:21)
System.Reflection.MethodBase:Invoke(Object, Object[])
NUnit.Core.Reflect:InvokeMethod(MethodInfo, Object, Object[])
NUnit.Core.Reflect:InvokeMethod(MethodInfo, Object)
NUnit.Core.TestMethod:RunSetUp()
NUnit.Core.TestMethod:RunTest()
NUnit.Core.NUnitTestMethod:RunTest()
NUnit.Core.TestMethod:RunRepeatedTest()
NUnit.Core.TestMethod:RunTestInContext()
NUnit.Core.TestMethod:Run(EventListener, ITestFilter)
NUnit.Core.TestSuite:RunAllTests(TestResult, EventListener, ITestFilter)
NUnit.Core.TestSuite:RunSuite(EventListener, ITestFilter)
NUnit.Core.TestSuite:RunSuiteInContext(EventListener, ITestFilter)
NUnit.Core.TestSuite:Run(EventListener, ITestFilter)
NUnit.Core.TestFixture:Run(EventListener, ITestFilter)
NUnit.Core.TestSuite:RunAllTests(TestResult, EventListener, ITestFilter)
NUnit.Core.TestSuite:RunSuite(EventListener, ITestFilter)
NUnit.Core.TestSuite:RunSuiteInContext(EventListener, ITestFilter)
NUnit.Core.TestSuite:Run(EventListener, ITestFilter)
NUnit.Core.TestSuite:RunAllTests(TestResult, EventListener, ITestFilter)
NUnit.Core.TestSuite:RunSuite(EventListener, ITestFilter)
NUnit.Core.TestSuite:RunSuiteInContext(EventListener, ITestFilter)
NUnit.Core.TestSuite:Run(EventListener, ITestFilter)
UnityTest.NUnitTestEngine:ExecuteTestSuite(TestSuite, ITestRunnerCallback, TestFilter) (at Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitTestEngine.cs:139)
UnityTest.NUnitTestEngine:RunTests(TestFilter, ITestRunnerCallback) (at Assets/UnityTestTools/UnitTesting/Editor/TestRunner/NUnitTestEngine.cs:91)
UnityTest.UnitTestView:StartTestRun(TestFilter, ITestRunnerCallback) (at Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunner.cs:84)
UnityTest.UnitTestView:RunTests(TestFilter) (at Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunner.cs:53)
UnityTest.UnitTestView:RunTests() (at Assets/UnityTestTools/UnitTesting/Editor/TestRunner/TestRunner.cs:35)
UnityTest.UnitTestView:OnGUI() (at Assets/UnityTestTools/UnitTesting/Editor/TestRunner/UnitTestView.cs:79)
UnityEditor.DockArea:OnGUI()

I've tried simply adding a component, by actionMaster = gameObject.GetComponent<ActionMaster>();, but I get a Null Point Error. How can I make this work without a warning?

PearsonArtPhoto
  • 38,970
  • 17
  • 111
  • 142

2 Answers2

5

MonoBehaviour's are expected to be instantiated into the scene on a GameObject - so you can't just call new because that isn't related to a game object.

To test a component derived from MonoBehaviour you need to create either instantiate a prefab (which has your component on it), or you need to create (or use an existing) GameObject and add your component:

GameObject go = new GameObject();
go.AddComponent<ActionMaster>();

Note: Whilst this is technically the answer to your question, you need to be aware that when you run the above, the Awake() call is run immeadiately, but the Start() and Update() will not run until the next frame - and your tests could be all over by that point.

peterept
  • 4,407
  • 23
  • 32
  • No worries. And hey, while you are getting into testing, also check out Unity's new assertion library: http://blogs.unity3d.com/2015/08/25/the-unity-assertion-library/ – peterept Nov 07 '15 at 01:05
  • So this code actually works, but it has the negative effect of adding objects to the Hierarchy. Any suggestion to make this work without the added game objects? – PearsonArtPhoto Nov 07 '15 at 02:10
  • Call Destroy(go); after your test to clean it up. – peterept Nov 07 '15 at 02:17
  • It requires DestroyImmediate, and oddly enough doesn't seem to destroy the object in the scene... Strange... Wonder if this is a bug... – PearsonArtPhoto Nov 07 '15 at 02:18
  • Destroy will remove it from the scene, but at the end of the frame.If it didn't remove it from the scene then the reference isn't correct any more (maybe you created multiple?). The other way is name your game object "test" and then remove all game objects with that name on teardown. – peterept Nov 07 '15 at 02:34
  • Something odd happened, but I fixed it by doing what I should have, adding ActionMaster to the hierarchy and finding it, as I answered. It was going to happen sooner or later, so I made it sooner. Thanks for the help! – PearsonArtPhoto Nov 07 '15 at 02:39
-1

@peterept's answer is mostly correct, but it actually creates objects in the Hierarchy. A better method is to actually create an object called ActionMaster, and then find it in code, as follows:

actionMaster= GameObject.FindObjectOfType<ActionMaster>();
PearsonArtPhoto
  • 38,970
  • 17
  • 111
  • 142