我有几个使用某些静态类的单元测试,例如:
public static class Utility
{
private static Data data;
public static void Init(Data data)
{
this.data = data;
}
public static void Process()
{
// Some actions that changes this.data (not reference, just inner Values)
}
}
public class Data
{
public List<string> Values { get; set; }
public void Add(string value)
{
Values.Add(value);
}
}
每个单元测试都会初始化Data实例并将其传递给Utility:
[Fact]
public void UnitTest1()
{
var data = new Data();
data.Add("val1");
Utility.Init(data);
Utility.Process();
// check changed data instance
}
[Fact]
public void UnitTest2()
{
var data = new Data();
data.Add("another_val1");
data.Add("another_val2");
Utility.Init(data);
Utility.Process();
// check changed data instance
}
如果我分别运行每个测试,则没有问题-没有失败的测试。 但是,如果我按顺序运行测试,则单元测试之一将失败,因为尽管调用了Utility.Init,但Utility.data包含来自先前测试的实例(短时间)。 如果我通过命令行运行测试(测试执行得非常快),则大部分测试很可能由于相同的原因而失败。我该如何解决这个问题?
答案 0 :(得分:3)
由于静态实用程序的性质,所有测试都在访问共享的静态资源,这可能已经产生负面影响。我建议使实用程序类成为实例类
public class Utility
{
private Data data;
public Utility(Data data) {
this.data = data;
}
public void Process() {
// Some actions that changes this.data (not reference, just inner Values)
}
}
哪个示例测试看起来像
[Fact]
public void UnitTest1() {
//Arrrange
var data = new Data();
data.Add("val1");
var subject = new Utility(data);
//Act
subject.Process();
//Assert
// check changed data instance
}
我怀疑初始化问题是XY problem,并且该实用程序还被用作生产中的静态依赖项,这是代码的味道。
在这种情况下,抽象静态实用程序类
public interface IUtility {
void Process(Data data);
}
并重构实现
public class Utility : IUtility {
public void Process(Data data) {
// Some actions that changes this.data (not reference, just inner Values)
}
}
这将导致测试看起来像
[Fact]
public void UnitTest1() {
//Arrrange
var data = new Data();
data.Add("val1");
var subject = new Utility();
//Act
subject.Process(data);
//Assert
// check changed data instance
}
[Fact]
public void UnitTest2() {
var data = new Data();
data.Add("another_val1");
data.Add("another_val2");
var subject = new Utility();
//Act
subject.Process(data);
//Assert
// check changed data instance
}
IUtility
将根据需要注入到相关类中,这将使生成的代码更可靠。