Điều tôi thường làm là tạo giao diện cho dịch vụ ứng dụng thực hiện chức năng này. Trong ví dụ của tôi, tôi sẽ giả sử bạn đang sử dụng một cái gì đó như MVVM Toolkit hoặc điều tương tự (vì vậy tôi có thể có được một ViewModel cơ bản và một RelayCommand).
Dưới đây là ví dụ về giao diện cực kỳ đơn giản để thực hiện các thao tác IO cơ bản như OpenFileDialog và OpenFile. Tôi đang hiển thị cả hai ở đây vì vậy bạn không nghĩ rằng tôi đề nghị bạn tạo một giao diện với một phương pháp để giải quyết vấn đề này.
public interface IOService
{
string OpenFileDialog(string defaultPath);
//Other similar untestable IO operations
Stream OpenFile(string path);
}
Trong ứng dụng của bạn, bạn sẽ cung cấp triển khai mặc định dịch vụ này. Đây là cách bạn sẽ tiêu thụ nó.
public MyViewModel : ViewModel
{
private string _selectedPath;
public string SelectedPath
{
get { return _selectedPath; }
set { _selectedPath = value; OnPropertyChanged("SelectedPath"); }
}
private RelayCommand _openCommand;
public RelayCommand OpenCommand
{
//You know the drill.
...
}
private IOService _ioService;
public MyViewModel(IOService ioService)
{
_ioService = ioService;
OpenCommand = new RelayCommand(OpenFile);
}
private void OpenFile()
{
SelectedPath = _ioService.OpenFileDialog(@"c:\Where\My\File\Usually\Is.txt");
if(SelectedPath == null)
{
SelectedPath = string.Empty;
}
}
}
Điều đó khá đơn giản. Bây giờ cho phần cuối cùng: testability. Điều này nên rõ ràng, nhưng tôi sẽ chỉ cho bạn cách thực hiện một thử nghiệm đơn giản cho việc này. Tôi sử dụng Moq cho stubbing, nhưng bạn có thể sử dụng bất cứ điều gì bạn muốn tất nhiên.
[Test]
public void OpenFileCommand_UserSelectsInvalidPath_SelectedPathSetToEmpty()
{
Mock<IOService> ioServiceStub = new Mock<IOService>();
//We use null to indicate invalid path in our implementation
ioServiceStub.Setup(ioServ => ioServ.OpenFileDialog(It.IsAny<string>()))
.Returns(null);
//Setup target and test
MyViewModel target = new MyViewModel(ioServiceStub.Object);
target.OpenCommand.Execute();
Assert.IsEqual(string.Empty, target.SelectedPath);
}
Điều này có thể hữu ích cho bạn.
Có thư viện trên CodePlex được gọi là "SystemWrapper" (http://systemwrapper.codeplex.com) có thể giúp bạn không phải làm một số lô của loại điều này. Dường như FileDialog chưa được hỗ trợ, vì vậy bạn chắc chắn sẽ phải viết một giao diện cho cái đó.
Hy vọng điều này sẽ hữu ích.
Sửa:
tôi dường như nhớ đến bạn ưu TypeMock Isolator cho khung giả mạo lòi của bạn. Đây là thử nghiệm tương tự bằng cách sử dụng Isolator:
[Test]
[Isolated]
public void OpenFileCommand_UserSelectsInvalidPath_SelectedPathSetToEmpty()
{
IOService ioServiceStub = Isolate.Fake.Instance<IOService>();
//Setup stub arrangements
Isolate.WhenCalled(() => ioServiceStub.OpenFileDialog("blah"))
.WasCalledWithAnyArguments()
.WillReturn(null);
//Setup target and test
MyViewModel target = new MyViewModel(ioServiceStub);
target.OpenCommand.Execute();
Assert.IsEqual(string.Empty, target.SelectedPath);
}
Hy vọng điều này cũng hữu ích.
Đây là một bản sao của: http://stackoverflow.com/questions/1043918/ open-file-dialog-mvvm –
Chắc chắn là. :-) Tôi đã thực hiện một số tìm kiếm trên SO trước khi đăng câu hỏi này, nó không xuất hiện. Oh well. –
Tôi đã bỏ phiếu để đóng câu hỏi này vì đây là một bản sao chính xác. –