MSTest中TestContext跨测试方法无法访问属性值的问题求助
问题
使用MSTest的TestContext时遇到异常:在Action1()测试方法中向TestContext添加属性后,在Action2()测试方法中无法获取该属性。Action1()里能正常输出属性值,但Action2()中访问不到。代码示例如下:
namespace API.Tests.Controllers { [TestClass] public class ControllerTests { private SomeController _controller; private SomeService _somService; public TestContext TestContext { get; set; } [TestInitialize] public void Initialize() { _someService = new SomeService(); } [TestMethod] public void Action2() { // Arrange var criteria = TestContext.Properties["id"]; <-- Can't access value here, it doesn't exist SomeController _controller = new SomeController(_someService); // Act IHttpActionResult result = _controller.Search((string)criteria); // Assert var contentResult = result as OkNegotiatedContentResult<List<Object>>; Assert.IsNotNull(result); Assert.IsInstanceOfType(result,typeof(OkNegotiatedContentResult<List<Object>>)); } [TestMethod] public void Action1() { // Arrange var testObj = new Obj { id = 10, name = "Test", code = "XXX" }; SomeController _controller = new SomeController(_someService); // Act IHttpActionResult result = _controller.Create(testObj); // Assert Assert.IsNotNull(result); Assert.IsInstanceOfType(result, typeof(OkNegotiatedContentResult<int>)); var content = result as OkNegotiatedContentResult<int>; TestContext.Properties.Clear(); TestContext.Properties.Add("id", content.Content.ToString()); Console.WriteLine(TestContext.Properties["id"]); <-- I can get the value here Console.WriteLine(TestContext.Properties.Count); <-- equal to 1 } } }
原因分析
MSTest的测试方法是完全独立执行的:
- 每个测试方法都会创建一个全新的
ControllerTests类实例 - 每个实例的
TestContext是独立的,属于当前测试实例私有 - 而且MSTest默认不保证测试方法的执行顺序,就算
Action1先跑,Action2也无法访问Action1所在实例的TestContext数据
解决办法
方案1:用静态字段共享数据
在测试类中定义静态字段存储需要传递的值,所有测试实例都能访问该字段:
namespace API.Tests.Controllers { [TestClass] public class ControllerTests { private SomeController _controller; private SomeService _someService; public TestContext TestContext { get; set; } // 静态字段跨实例共享数据 private static string _sharedTestId; [TestInitialize] public void Initialize() { _someService = new SomeService(); } [TestMethod] // 指定执行顺序,确保Action1先跑 [TestProperty("Priority", "1")] public void Action1() { // Arrange & Act 逻辑不变 var content = result as OkNegotiatedContentResult<int>; // 将值存入静态字段 _sharedTestId = content.Content.ToString(); } [TestMethod] [TestProperty("Priority", "2")] public void Action2() { // 直接使用静态字段中的值 var criteria = _sharedTestId; SomeController _controller = new SomeController(_someService); // Act & Assert 逻辑不变 } } }
注意:这种方式会让测试产生耦合,必须保证执行顺序,仅在必要时使用。
方案2:重构测试,保证独立性(推荐)
让每个测试方法独立运行,不依赖其他测试的输出。可以封装公共逻辑来生成所需数据:
namespace API.Tests.Controllers { [TestClass] public class ControllerTests { private SomeController _controller; private SomeService _someService; public TestContext TestContext { get; set; } [TestInitialize] public void Initialize() { _someService = new SomeService(); } [TestMethod] public void Action2() { // 直接调用公共方法生成所需id,不依赖Action1 var criteria = CreateTestObjectAndGetId(); SomeController _controller = new SomeController(_someService); // Act & Assert 逻辑不变 } [TestMethod] public void Action1() { // Arrange & Act & Assert 逻辑不变 } // 封装公共逻辑,创建测试对象并返回生成的id private string CreateTestObjectAndGetId() { var testObj = new Obj { id = 10, name = "Test", code = "XXX" }; var tempController = new SomeController(_someService); var result = tempController.Create(testObj); var content = result as OkNegotiatedContentResult<int>; return content.Content.ToString(); } } }
这种方式遵循单元测试的独立性原则,测试结果不受执行顺序影响,是更优的选择。
方案3:使用TestRun级别的Properties
如果一定要用TestContext传递数据,可以使用TestContext.TestRun.Properties,它属于整个测试运行会话,而非单个测试实例:
// Action1中添加数据 TestContext.TestRun.Properties.Add("id", content.Content.ToString()); // Action2中获取数据 var criteria = TestContext.TestRun.Properties["id"];
同样需要注意执行顺序问题,且该数据会在整个测试运行期间保留,可能影响其他测试用例。
内容的提问来源于stack exchange,提问作者invaders7vn
相关产品推荐
相关产品推荐

