如何在单元测试中模拟ComputePrice函数内Config实例的变量值?
解决ComputePrice单元测试中Config实例属性模拟问题
方案1:直接设置Config实例属性(最简单快速的方法)
因为Config.Instance返回的是可修改属性的实例,你可以在测试的Arrange阶段直接给example1和example2赋值,覆盖默认的0值。修改后的测试代码如下:
public class Tests { [Test] public void TestComputePrice() { // Arrange double a = 1; // 直接设置Config实例的配置值 Config.Instance.example1 = 1; Config.Instance.example2 = 2; // 预期结果:1*2 +1 =3 double expectedResult = 3; // Act double testedResult = Data.ComputePrice(a); // Assert Assert.AreEqual(expectedResult, testedResult); } }
如果测试用例之间需要隔离配置值,记得在每个测试前后重置Config属性,避免用例互相影响:
[SetUp] public void Setup() { // 重置为默认值 Config.Instance.example1 = 0; Config.Instance.example2 = 0; }
方案2:重构代码解耦(更符合测试友好的设计)
当前ComputePrice是静态方法且直接依赖单例Config,耦合度高,不利于长期维护和测试。推荐重构代码解耦配置依赖:
方式A:将Config作为参数传入
修改ComputePrice方法,让它接受Config实例作为参数:
public static double ComputePrice(double a, Config config) { double c = config.example1; double d = config.example2; return c * d + a; }
测试时直接传入自定义的Config实例:
[Test] public void TestComputePrice() { // Arrange double a = 1; var testConfig = new Config { example1 = 1, example2 = 2 }; double expectedResult = 3; // Act double testedResult = Data.ComputePrice(a, testConfig); // Assert Assert.AreEqual(expectedResult, testedResult); }
方式B:依赖注入(适合非静态场景)
如果Data类可以改为非静态,通过构造函数注入Config:
public class Data { private readonly Config _config; public Data(Config config) { _config = config; } public double ComputePrice(double a) { double c = _config.example1; double d = _config.example2; return c * d + a; } }
测试时注入自定义的Config实例:
[Test] public void TestComputePrice() { // Arrange double a = 1; var testConfig = new Config { example1 = 1, example2 = 2 }; var data = new Data(testConfig); double expectedResult = 3; // Act double testedResult = data.ComputePrice(a); // Assert Assert.AreEqual(expectedResult, testedResult); }
方案3:反射重置Config单例(不推荐,仅当无法修改现有代码时使用)
如果不能修改Data和Config的代码,可以用反射重置Config的_Instance字段,替换为自定义实例:
[Test] public void TestComputePrice() { // Arrange double a = 1; // 创建自定义Config实例 var testConfig = new Config { example1 = 1, example2 = 2 }; // 用反射获取并重置_Instance字段 var instanceField = typeof(Config).GetField("_Instance", BindingFlags.NonPublic | BindingFlags.Static); instanceField.SetValue(null, new Lazy<Config>(() => testConfig)); double expectedResult = 3; // Act double testedResult = Data.ComputePrice(a); // Assert Assert.AreEqual(expectedResult, testedResult); }
这种方法属于hack手段,会破坏封装性,仅作为临时解决方案,优先推荐方案1或方案2。
内容的提问来源于stack exchange,提问作者w97802
相关产品推荐
相关产品推荐

