我已经将我的项目精简到最低限度,试图找出Unity TestRunner挂起的这个实例。 我有两个 Monobehaviors 类,GameController 和 TrialController。 我关注了Jason Wiemann的优秀测试视频 您需要了解的有关在Unity3D中进行测试和针对Mocks的单行为测试的所有信息,以创建一个接口类ITrialController,以便我可以模拟它来测试GameController。 当我尝试运行TestWithGetNextSubstitute((时,TestRunner挂起。 我在这里做错了什么?
==============游戏控制测试.cs ===
==========================using System.Collections;
using System.Collections.Generic;
using NSubstitute;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class GameCtrlTest
{
GameController gameCtrl;
[SetUp]
public void TestSetup()
{
GameObject gameObject = new GameObject("GameController");
gameCtrl = gameObject.AddComponent<GameController>();
gameCtrl.trialCtrl = Substitute.For<ITrialController>();
Assert.IsNotNull(gameCtrl.trialCtrl);
Debug.Log("Test Setup() done");
}
[UnityTest]
public IEnumerator TestWithGetNextSubstitute()
{
gameCtrl.trialCtrl.GetNextTrial().Returns( "test-1", "test-2", null);
yield return null;
}
}
}
================== 审判控制器.cs ===
================================using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
public class TrialController : MonoBehaviour, ITrialController
{
int trialsLeft = 2;
public string GetNextTrial()
{
if (trialsLeft == 0)
return null;
else
{
string returnString = "trial--" + trialsLeft;
trialsLeft--;
return (returnString);
}
}
}
==================ITrialController.cs ==
===============public interface ITrialController
{
string GetNextTrial();
}
==================游戏控制器.cs ===
================using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// give Test Runner access to internal variables and methods
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Tests")]
public class GameController : MonoBehaviour
{
public ITrialController trialCtrl { get; set; }
//=================== MonoBehavior interface =======================
void Awake()
{
Debug.Log("gameController Awake()");
}
// Start is called before the first frame update
void Start()
{
Debug.Log("gameController Start()");
if (trialCtrl != null)
Debug.Log("trialCtrl already set");
else
{
Debug.Log("calling FindObjectOfType(typeof(TrialController)");
trialCtrl = (ITrialController)FindObjectOfType(typeof(TrialController));
Debug.Assert(trialCtrl != null, "Problem finding TrialController");
}
}
// Update is called once per frame
static bool levelInitialized = false;
void Update()
{
if (!levelInitialized)
{
Debug.Log("gameController first Update()");
levelInitialized = true;
}
string trialName = trialCtrl.GetNextTrial();
while (trialName != null)
{
Debug.Log($"GameController got {trialName} from GetNextTrial");
trialName = trialCtrl.GetNextTrial();
}
}
}
解决方法是移动 GetNextTrial((。返回从 [UnityTest] 到 [Setup] 的 (( 调用。 这最初似乎非常有限,但可能有一种方法可以将参数列表("test-1"、"test-2"、null(移动到变量中,以便我可以针对不同的测试更改它。
==============游戏Ctrl测试.cs ===
====================================using System.Collections;
using System.Collections.Generic;
using NSubstitute;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class GameCtrlTest
{
GameController gameCtrl;
[SetUp]
public void TestSetup()
{
GameObject gameObject = new GameObject("GameController");
gameCtrl = gameObject.AddComponent<GameController>();
gameCtrl.trialCtrl = Substitute.For<ITrialController>();
Assert.IsNotNull(gameCtrl.trialCtrl);
gameCtrl.trialCtrl.GetNextTrial().Returns("test-1", "test-2", null);
Debug.Log("Test Setup() done");
}
[UnityTest]
public IEnumerator TestWithGetNextSubstitute()
{
yield return null;
}
}
}