Search Unity

Unit Testing with Monobehaviour

Discussion in 'Testing & Automation' started by MrBunny, Sep 10, 2020.

  1. MrBunny

    MrBunny

    Joined:
    May 2, 2014
    Posts:
    3
    Hello Everyone,
    I know this topic has a lot. With different solutions out there. After doing some research I was wondering is this a horrible approach?

    I'm not doing an abstract class as I found in the research that the magic functions (Update, Start, etc...) kill the performance and it seems like the other approach is humble object pattern. I was thinking of wrapping all the methods within mono as I need them. This Solution wouldn't help directly with the magic functions but I felt like testing those as just straight public functions would be acceptable.

    https://blogs.unity3d.com/2014/06/03/unit-testing-part-2-unit-testing-monobehaviours/
    https://blogs.unity3d.com/2015/12/23/1k-update-calls/

    As Example

    Code (CSharp):
    1.  
    2.  
    3. public interface IMonoWrap
    4. {
    5.     T InstantiateWrap<T>(T original, Transform parent) where T : Object;
    6. }
    7.  
    8. public class MonoWrap : MonoBehaviour, IMonoWrap
    9. {
    10.     public T InstantiateWrap<T>(T original, Transform parent) where T : Object
    11.     {
    12.         return Instantiate(original, parent);
    13.     }
    14. }
    15.  
    16. public class HeaderController : MonoBehaviour
    17. {
    18.     public IMonoWrap monoWrap;
    19.  
    20.     public AccountController accountPrefab;
    21.  
    22.     private AccountController _accountController;
    23.  
    24.     public void Start()
    25.     {
    26.         monoWrap = new GameObject().AddComponent<MonoWrap>();
    27.     }
    28.  
    29.     public void ShowAccountSettings()
    30.     {
    31.         if (_accountController == null)
    32.         {
    33.             _accountController = monoWrap.InstantiateWrap(accountPrefab, this.transform);
    34.         } else
    35.         {
    36.             _accountController.gameObject.SetActive(true);
    37.         }
    38.     }
    39. }
    40.  
    My Test

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using NUnit.Framework;
    4. using UnityEngine;
    5. using UnityEngine.TestTools;
    6. using NSubstitute;
    7.  
    8. namespace Tests
    9. {
    10.     public class HeaderControllerTests
    11.     {
    12.         private HeaderController SUT;
    13.  
    14.         [SetUp]
    15.         public void Setup()
    16.         {
    17.             var go = new GameObject();
    18.             SUT = go.AddComponent<HeaderController>();
    19.             SUT.accountPrefab = new GameObject().AddComponent<AccountController>();
    20.             SUT.accountPrefab.gameObject.name = "Account";
    21.             SUT.monoWrap = Substitute.For<IMonoWrap>();
    22.         }
    23.  
    24.         [TearDown]
    25.         public void TearDown()
    26.         {
    27.             UnityEngine.Object.DestroyImmediate(SUT.gameObject);
    28.         }
    29.  
    30.         [Test]
    31.         public void SimpleTest()
    32.         {
    33.            
    34.         }
    35.  
    36.         [Test]
    37.         public void ShouldAccountShowSettings()
    38.         {
    39.             SUT.ShowAccountSettings();
    40.             SUT.monoWrap.Received().InstantiateWrap(SUT.accountPrefab, SUT.gameObject.transform);
    41.         }
    42.     }
    43. }
    44.