问题
I'm having a problem with the classinitilalize method of a unit test being executed after the evaluation of the attributes on a unit test. These tests use a [classinitialize] method to generate a test set that makes a random set of data in an xml file. The xml file is consumed by a unit test with the attribute [datasource]. A trimmed down version of this looks like this:
[ClassInitialize]
public static void Initialize(TestContext context)
{
// Create xml output file
var output = new XDocument(new XElement("Rows"));
foreach (var Code in Codes)
{
if (output.Root != null)
output.Root.Add(new XElement("Row", new XElement("Code", Code)));
}
output.Save("TestData.xml");
}
[DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML",
"|DataDirectory|\\TestData.xml",
"Row",
DataAccessMethod.Sequential)]
[TestMethod]
public void TestStuff()
{
var Code = (string)TestContext.DataRow["Code"];
TestItem(Code);
}
I'm working with Visual Studio 2012 Update 3. I have used the Sysinternals tool Process Monitor to verify the order of execution. I set a break point at the beginning of each method. I then stepped through and watched the file access. The order of operations I saw.
- TestData.xml read by vstestexecutionengine.
- ClassInitialize Method is called and writes TestData.xml
- TestMethod is executed, using data read in step 1. (I added a file with bogus data to test)
So my question is, what am I doing wrong that classinitialize is not executing before the xml file is read? Or is what I am trying to do impossible?
回答1:
MSTestHacks might be a possible workaround for you.
It allows an IEnumberable on your test class to be used as the DataSource for your TestMethod. You can return what you have as Codes in this property.
From the website:
Runtime DataSource
You MUST inherit your test class from TestBase
[TestClass]
public class UnitTest1 : TestBase
{ }
Create a Property, Field or Method, that returns an IEnumerable
[TestClass]
public class UnitTest1 : TestBase
{
private IEnumerable<int> Stuff
{
get
{
//This could do anything, fetch a dynamic list from anywhere....
return new List<int> { 1, 2, 3 };
}
}
}
Add the DataSource attribute to your test method, pointing back to the IEnumerable name created earlier. This needs to be fully qualified.
[TestMethod]
[DataSource("Namespace.UnitTest1.Stuff")]
public void TestMethod1()
{
var number = this.TestContext.GetRuntimeDataSourceObject<int>();
Assert.IsNotNull(number);
}
来源:https://stackoverflow.com/questions/18217226/forcing-classinitialize-to-execute-before-testmethod-data-is-read