我有一个像组件一样的资源管理器,它实际上处理文件系统。如何开始将单元测试编写到这些需要使用剪贴板的方法,以及文件系统中文件的实际移动或复制?
我尝试过看教程和在线课程,但是它们太抽象了,对我当前的问题无法帮助我。
public void DoCtrlV(object obj)
{
try
{
StopWait();
var list = System.Windows.Clipboard.GetFileDropList();
if (list.Count > 0) // i.e. from outside - get file list
{
if (!PasteFromOutsideSucceeded(list))
return;
}
else // i.e. from inside
{
string targetFolder = GetTargetFolder();
if (Globals.ListInternalUseCopy != null) // from list
{
PasteFromList(targetFolder);
}
else if (Globals.TreeInternalUseCopy != null) // from tree
{
PasteFromTree(targetFolder);
}
}
RefreshBothControls();
}
catch (UnauthorizedAccessException ex)
{
// doesn't matter atm
}
}
编辑/更新:我必须做很多事情,而且我还处于中点,但这是我到目前为止所做的。
我的DoCtrlV现在看起来像这样:
StopWait();
var list = System.Windows.Clipboard.GetFileDropList();
var result = _hadnler.PerformPaste(Globals.ListInternalUseCopy, Globals.TreeInternalUseCopy, list, MoveNotCopy, shellList.Path, shellTree.SelectedPath);
if (!result)
MessageBox.Show("Please select a destiantion.");
RefreshBothControls();
我唯一测试(atm)的是_hadnler.PerformPaste。
正如您所看到的,我现在决定忽略剪贴板和其他因素,只关注FileSystem操作。我的PerformPaste现在看起来像这样:
public bool PerformPaste(List<string> listInternalUseCopy, string treeInternalUseCopy, StringCollection clipboardList, bool moveNotCopy, string listPath, string treePath)
{
if (clipboardList.Count > 0) // i.e. from outside - get file list
{
if (!PasteFromOutsideSucceeded(clipboardList, listPath))
return false;
}
else // i.e. from inside
{
string targetFolder = GetTargetFolder(listPath, treePath);
if (listInternalUseCopy != null) // from list
{
PasteFromList(targetFolder, moveNotCopy);
}
else if (treeInternalUseCopy != null) // from tree
{
PasteFromTree(targetFolder, moveNotCopy);
}
}
return true;
}
我的PerformPaste仍然调用子方法,但现在它们都是&#34; Ok&#34;。最后,主要的问题是你得到了File.Move或File.Copy - 这就是我需要处理它的原因。所以我安装了System.IO.Abstractions NuGet包,并更改了我的代码以支持IFileSystem(基本上通过在我的新IFileSystem对象调用中添加来替换所有IO调用)。在实际代码中,它被设置为常规文件系统,在testcode中,它是一个模拟文件系统(也由一个名为System.IO.Abstractions.TestingHelpers的子NuGet包支持)。
我的测试代码现在看起来像这样:
public class MainLogicHandlerTests
{
private readonly MockFileSystem fileSystem;
public MainLogicHandlerTests()
{
fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
{
{ @"c:\src\file1.txt", new MockFileData("Test1") },
{ @"c:\src\file2.txt", new MockFileData("Test2") },
{ @"c:\dst\file3.txt", new MockFileData("Test3") }
});
FileSystem.UsedFileSystem = fileSystem;
}
[TestMethod()]
public void PasteOneFile_FromOutsideIntoList_ShouldSucceed()
{
//Arrange
List<string> listInternal = new List<string>() { @"c:\src\file1.txt"};
string treeInternal = null;
StringCollection clipboardList = new StringCollection();
clipboardList.Add(@"c:\src\file1.txt");
bool moveNotCopy = false;
string listPath = @"c:\dst";
string treePath = @"c:\dst";
//Act
var sut = new MainLogicHandler(null);
var result = sut.PerformPaste(listInternal, treeInternal, clipboardList, moveNotCopy, listPath, treePath);
//Assert
Assert.IsTrue(fileSystem.FileExists(@"c:\dst\file1.txt"));
}
}
所以还有很长的路要走,但至少这是一个开始。将会感谢你们有更多的提示......
答案 0 :(得分:6)
这就是我通常对单元测试这样做的事情。 从我的方法中获取依赖于非单元可测试内容的代码。
例如,System.Windows.Clipboard.GetFileDropList不受您的控制,不应进行单元测试(它是外部依赖项)。为了使其不受单元测试的影响,您需要使用依赖注入。
创建一个类似于此的界面:
public interface IClipboard
{
StringCollection GetClipBoardInfo();
}
将从此继承的类注入DoCtrlV方法。
public void DoCtrlV(object obj, IClipboard clipboard)
创建一个实现该方法的接口版本的类,并返回正确的剪贴板函数:
public StringCollection GetClipBoardInfo()
{
System.Windows.Clipboard.GetFileDropList();
}
现在,为单元测试创建一个类,它只返回一个StringCollection并告诉你该方法是否被调用。
public MockClipboard
{
public StringCollection GetClipBoardInfo()
{
ClipboardWasRead = true;
StringCollection col = new StringCollection();
col.Add("...");
return col;
}
public bool ClipboardWasRead { get; set; }
}
这样您就不会对不在您控制范围内的东西进行单元测试(如剪贴板和文件系统)。如果要测试方法是否读取剪贴板,可以测试方法的ClipboardWasRead布尔值。 这里真正重要的是你需要重写你的方法以使其更具单元可测试性。你现在编写的代码有很多外部依赖,例如:
一次只能处理它们,直到您觉得您的代码可以根据自己的喜好进行测试为止。
这是一个示例测试,它将告诉您方法是否实际尝试读取剪贴板。
[TestMethod]
public void WasClipboardRead()
{
// Arrange
var mock = new MockClipboard();
var obj = new Object();
// Act
DoCtrlV(obj, mock);
// Assert
Assert.IsTrue(mock.ClipboardWasRead);
}