单元测试需要读取文件。我如何使它便携?
我正在与另一位开发人员开发一个开源项目。我正在研究需要读取默认自定义xml配置文件的单元测试。我只能保证回购中的路径部分将在他的机器上。我怎样才能重写这个测试,使其可移植?我不希望测试每次检查代码时都会出现失败。单元测试需要读取文件。我如何使它便携?
public class ConfigurationTests
{
[TestMethod]
public void ConfigurationLoads()
{
//todo: how do I make this test portable?
const string configFile = @"C:\Users\Christopher\Source\Repos\RetailCoderVBE\RetailCoder.VBE\Config\rubberduck.config";
var deserializer = new XmlSerializer(typeof(Rubberduck.Config.Configuration));
using (StreamReader reader = new StreamReader(configFile))
{
Rubberduck.Config.Configuration config = (Rubberduck.Config.Configuration)deserializer.Deserialize(reader);
Assert.IsNotNull(config);
}
}
}
这是我保证其他开发者将拥有的路径的一部分。在此之前,我需要以某种方式动态获取。
\RetailCoderVBE\RetailCoder.VBE\Config\rubberduck.config
你应该做的是创建一个接口到一个文件系统,并在测试嘲笑它。访问真实文件系统的这个接口的实现你不能测试,所以它必须尽可能简单。由于XmlSerializer.Deserialize方法接受Stream,因此您的接口可以返回Stream。
public interface IFileAccess
{
Stream GetFileStream(string fileName);
}
public class RealFileAccess : IFileAccess
{
public Stream GetFileStream(string fileName)
{
....
}
}
public class ConfigLoader
{
Rubberduck.Config.Configuration LoadConfiguration(IFileAccess fileAccess)
{
const string configFile = @"C:\Users\Christopher\Source\Repos\RetailCoderVBE\RetailCoder.VBE\Config\rubberduck.config";
var deserializer = new XmlSerializer(typeof(Rubberduck.Config.Configuration));
return (Rubberduck.Config.Configuration)deserializer.Deserialize(fileAccess.GetFileStream(configFile));
}
}
然后测试将
[TestMethod]
public void ConfigurationLoads()
{
const string configFile = @"C:\Users\Christopher\Source\Repos\RetailCoderVBE\RetailCoder.VBE\Config\rubberduck.config";
IFileAccess fileAccess = Mock.Of<IFileAccess>();
// setup fileAccess
Rubberduck.Config.Configuration config = new ConfigLoader().LoadConfiguration(fileAccess);
Assert.IsNotNull(config);
Mock.Get(fileAccess).Verify(fa => fa.GetFileStream(configFile));
}
然后,您可以甚至是否GetFileStream用正确的参数调用。
非常感谢。这是我需要看到的。我会稍后再尝试。你可能想从你的答案中删除'const string configFile ...'行。这条路线不再需要。 – RubberDuck 2014-11-21 13:28:00
我将它留在那里,以便您可以声明它在GetFileStream调用中使用。我将添加断言。 – 2014-11-21 13:41:42
我的工作需要在一个默认的自定义XML配置文件读取单元测试。
以上强烈表明它不是真正的单元测试。他们(理想上)独立于外部世界。 为什么你需要读取配置文件?什么信息存储在配置中?也许可以使用测试将带有虚拟信息的配置文件添加到项目中,或者使用某个接口将依赖项存储到文件系统。
的标准方法这样做看起来就像
interface IConfigReader{
object GetValue(string key);
}
// later in code
var configDate = _reader.GetValue("ConnectionString");
据我所知,单元测试不应该依赖于系统外部的任何东西 - 正是因为配置不能保证是可移植的。 – Gigi 2014-11-21 13:04:25
这个'TestMethod'应该测试什么?现在,它只测试'XmlSerializer.Deserialize'返回'Rubberduck.Config.Configuration'的实例......但你不是'XmlSerializer'的作者,所以测试它是没有意义的。 – 2014-11-21 13:04:37
对。这就是我问的原因。你如何建议我重写我的测试,以便我不依赖文件?我是单元测试新手,所以我不知道在这里做什么@Gigi。 – RubberDuck 2014-11-21 13:07:47