You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NUnit配合Unity使用TestCaseSource首次运行参数为null问题

问题原因

  • NUnit的TestCaseSource属性对应的数据源会在测试用例发现阶段执行,这个阶段远早于测试用例的执行阶段,而[OneTimeSetUp]标记的方法只会在测试用例正式执行前才会运行。
  • 首次编译后运行测试时,测试用例发现阶段读取TestRunning静态属性返回测试参数,此时m_expired和m_current两个静态字段还没有被OneTimeSetUp赋值,所以拿到的是null,测试执行时参数已经固定为null,因此报错。
  • 第二次运行测试时,上一次测试执行时OneTimeSetUp已经给静态字段完成了赋值,且Unity测试运行环境不会主动清空静态字段的值,因此测试发现阶段能拿到正确的参数,测试正常通过。

解决方案

方案1:使用Lazy做统一延迟初始化(推荐)

用静态的Lazy对象统一管理测试数据的初始化,保证无论测试发现阶段还是执行阶段先访问,都能拿到已经加载完成的数据,避免重复编写加载逻辑:

[TestFixture]
public class TestBase
{
    private string m_filePath = "UnitTest\\response.json";

    protected static Event m_current;
    protected static Event m_expired;

    protected LoginResponse m_response;

    // 新增静态Lazy对象统一处理数据加载,仅会执行一次初始化
    private static Lazy<LoginResponse> s_testData = new Lazy<LoginResponse>(() => 
    {
        string path = System.IO.Path.Combine(Application.dataPath, "UnitTest\\response.json");
        string txt = File.ReadAllText(path);
        return JsonFx.Json.JsonReader.Deserialize<LoginResponse>(txt);
    });

    public static IEnumerable<TestCaseData> TestRunning
    {
        get
        {
            yield return new TestCaseData(s_testData.Value.events[0], false);
            yield return new TestCaseData(s_testData.Value.events[1], true);
        }
    }

    [OneTimeSetUp]
    public virtual void SetUp()
    {
        m_response = s_testData.Value;
        m_expired = m_response.events[0];
        m_current = m_response.events[1];
    }

    protected class LoginResponse
    {
        public List<Event> events;
    }
}

方案2:将数据加载逻辑直接嵌入TestRunning访问器

直接在TestRunning属性的get方法中完成数据加载,保证测试用例发现阶段读取参数时,数据已经完成初始化:

public static IEnumerable<TestCaseData> TestRunning
{
    get
    {
        // 数据未加载时先执行加载逻辑
        if (m_expired == null || m_current == null)
        {
            string path = System.IO.Path.Combine(Application.dataPath, "UnitTest\\response.json");
            string txt = File.ReadAllText(path);
            var response = JsonFx.Json.JsonReader.Deserialize<LoginResponse>(txt);
            m_expired = response.events[0];
            m_current = response.events[1];
        }
        yield return new TestCaseData(m_expired, false);
        yield return new TestCaseData(m_current, true);
    }
}

提示:如果是在播放模式下运行测试,不能直接访问Application.dataPath读取文件,需要将测试配置文件放到Resources目录下,通过Resources.LoadAPI读取。

内容的提问来源于stack exchange,提问作者fafase

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 11:51:02