NUnit TestCaseSource 第一个为空 运行
NUnit TestCaseSource null on first run
使用 NUnit 和 Unity 我有一个基础 class 用于测试:
[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;
public static IEnumerable<TestCaseData> TestRunning
{
get
{
yield return new TestCaseData(m_expired, false);
yield return new TestCaseData(m_current, true);
}
}
[OneTimeSetUp]
public virtual void SetUp()
{
string path = System.IO.Path.Combine(Application.dataPath, m_filePath);
string txt = File.ReadAllText(path);
m_response = JsonFx.Json.JsonReader.Deserialize<LoginResponse>(txt);
m_expired = m_response.events[0];
m_current = m_response.events[1];
}
protected class LoginResponse
{
public List<Event> events;
}
}
然后我在使用 TestRunning 集合的子 class 中有一个 TestCaseSource,重新编译后它将在第一个 运行 测试中失败。如果我 运行 再次测试,它们就会通过。
第一个对象在测试中为空。
sub class 没有设置,因此它不会阻止调用。
有多种方法可以解释 NUnit 在测试中执行各种操作的顺序,具有不同的详细程度。这是可能的最高级别...
所有与发现测试有关的操作。这包括查找和解释所有提供数据的属性,包括 [TestCase]
、[TestCaseSource]
、[Values]
等
与执行已发现的测试有关的所有操作。这包括执行所有 OneTimeSetup
和 SetUp
方法、测试方法本身以及任何 TearDown
和 OneTimeTearDown
方法。
在第 2 组中,关于首先执行哪些特定操作有相当复杂的规则,但即使是最早的操作(例如基础 class OneTimeSetUp
方法)也永远不会在第 1 组中的操作已完成。
这种严格排序的原因是第 1 组中的属性不仅仅提供供 运行 测试使用的数据。他们还确定找到了多少测试。也就是说,具有五组值的 TestCaseSource
创建五个测试,具有 100 组的 TestCaseSource
创建 100 个测试。
理解了这一点,解决起来就很简单了。您的 TestCaseSource
必须实际阅读 json 文件并根据在那里找到的内容创建案例。这意味着您的源可能需要是一个方法而不是一个简单的集合。
根据@Charlie 的回答,这里是解决我的问题所需的修改:
public class TestBase
{
private string m_filePath = "UnitTest\response.json";
protected static Event m_current;
protected static Event m_expired;
protected static LoginResponse m_response;
public static IEnumerable<TestCaseData> TestRunning
{
get
{
if(m_response == null)
{
SetUpTest();
}
yield return new TestCaseData(m_expired, false);
yield return new TestCaseData(m_current, true);
}
}
[OneTimeSetUp]
public virtual void SetUp()
{
SetUpTest();
}
protected class LoginResponse
{
public List<Event> events;
}
private static void SetUpTest()
{
string path = System.IO.Path.Combine(Application.dataPath, m_filePath);
string txt = File.ReadAllText(path);
m_response = JsonFx.Json.JsonReader.Deserialize<LoginResponse>(txt);
m_expired = m_response.events[0];
m_current = m_response.events[1];
}
}
使用 NUnit 和 Unity 我有一个基础 class 用于测试:
[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;
public static IEnumerable<TestCaseData> TestRunning
{
get
{
yield return new TestCaseData(m_expired, false);
yield return new TestCaseData(m_current, true);
}
}
[OneTimeSetUp]
public virtual void SetUp()
{
string path = System.IO.Path.Combine(Application.dataPath, m_filePath);
string txt = File.ReadAllText(path);
m_response = JsonFx.Json.JsonReader.Deserialize<LoginResponse>(txt);
m_expired = m_response.events[0];
m_current = m_response.events[1];
}
protected class LoginResponse
{
public List<Event> events;
}
}
然后我在使用 TestRunning 集合的子 class 中有一个 TestCaseSource,重新编译后它将在第一个 运行 测试中失败。如果我 运行 再次测试,它们就会通过。 第一个对象在测试中为空。
sub class 没有设置,因此它不会阻止调用。
有多种方法可以解释 NUnit 在测试中执行各种操作的顺序,具有不同的详细程度。这是可能的最高级别...
所有与发现测试有关的操作。这包括查找和解释所有提供数据的属性,包括
[TestCase]
、[TestCaseSource]
、[Values]
等与执行已发现的测试有关的所有操作。这包括执行所有
OneTimeSetup
和SetUp
方法、测试方法本身以及任何TearDown
和OneTimeTearDown
方法。
在第 2 组中,关于首先执行哪些特定操作有相当复杂的规则,但即使是最早的操作(例如基础 class OneTimeSetUp
方法)也永远不会在第 1 组中的操作已完成。
这种严格排序的原因是第 1 组中的属性不仅仅提供供 运行 测试使用的数据。他们还确定找到了多少测试。也就是说,具有五组值的 TestCaseSource
创建五个测试,具有 100 组的 TestCaseSource
创建 100 个测试。
理解了这一点,解决起来就很简单了。您的 TestCaseSource
必须实际阅读 json 文件并根据在那里找到的内容创建案例。这意味着您的源可能需要是一个方法而不是一个简单的集合。
根据@Charlie 的回答,这里是解决我的问题所需的修改:
public class TestBase
{
private string m_filePath = "UnitTest\response.json";
protected static Event m_current;
protected static Event m_expired;
protected static LoginResponse m_response;
public static IEnumerable<TestCaseData> TestRunning
{
get
{
if(m_response == null)
{
SetUpTest();
}
yield return new TestCaseData(m_expired, false);
yield return new TestCaseData(m_current, true);
}
}
[OneTimeSetUp]
public virtual void SetUp()
{
SetUpTest();
}
protected class LoginResponse
{
public List<Event> events;
}
private static void SetUpTest()
{
string path = System.IO.Path.Combine(Application.dataPath, m_filePath);
string txt = File.ReadAllText(path);
m_response = JsonFx.Json.JsonReader.Deserialize<LoginResponse>(txt);
m_expired = m_response.events[0];
m_current = m_response.events[1];
}
}