我有以下场景,到目前为止我还没有使用过Ninject。我有以下类结构(简化以便于阅读:])。首先是所有IDocument
s的抽象基类
public abstract class DocumentController : IDocumentController, IDisposable
{
...
private IMessageBoxService messageBoxService;
private IUndoRedoManager undoRedoManager;
private FileSystemObserver observer;
private bool fileChanging;
public DocumentController(IMessageBoxService messageBoxService)
{
if (messageBoxService == null)
throw new ArgumentNullException("messageBoxService");
this.messageBoxService = messageBoxService;
}
...
private void FileChangedHandler(string p)
{
if (!fileChanging && p.CompareNoCase(FilePath))
{
fileChanging = true;
try
{
(View as Form).UIThread(() =>
{
DialogResult result = messageBoxService.DisplayMessage(
(Form)View,
String.Format(
MessageStrings.DocumentController_DocumentChanged,
FilePath,
Constants.Trademark),
CaptionStrings.ChangeNotification,
MessageBoxButtons.YesNo, MessageBoxIcon.Information);
if (result == DialogResult.Yes)
{
if (TryClose(new FormClosingEventArgs(CloseReason.None, false)))
{
MediatorService.Instance.NotifyColleagues(
MediatorService.Messages.OpenDocuments,
new List<string>() { FilePath });
Dispose();
}
}
});
}
finally
{
fileChanging = false;
}
}
}
// Omitted code for not saved prompt for brevity.
}
此类监视所有打开的文档,如果在文件系统中更改它们,则会显示提示。如果在他们处于&#34;脏&#34;状态,相同IMessageBoxService
提示保存。
派生的具体类ctors的一个例子是
public class TextEditorController : DocumentController, IZoom
{
...
public TextEditorController(ITextEditorView view, IMessageBoxService messageBoxService)
: base(messageBoxService)
{
if (view == null)
throw new ArgumentNullException("view");
this.view = view;
InitializeEventHandlers();
}
...
}
现在使用该应用程序时效果很好。我遇到的问题是单元测试。我想要做的是编写一个单元测试,打开我的文本文档,进行一些更改,然后尝试关闭它们,如果它们是&#34;脏&#34; /未保存。这将显示一个消息框,但我想模拟IMessageBoxService
并测试消息框是否确实在正确的条件下显示。我有以下单元测试类
[TestClass]
public class DocumentManagementTests
{
private IDocumentProvider documentProvider;
private Moq.Mock<IProgress<string>> mockProgress;
private List<string> filePaths = new List<string>();
#region Initialization.
[TestInitialize]
public void Initialize()
{
documentProvider = CompositionRoot.Resolve<IDocumentProvider>();
if (documentProvider == null)
throw new ArgumentNullException("documentManager");
mockProgress = new Mock<IProgress<string>>();
mockProgress.Setup(m => m.Report(It.IsAny<string>()))
.Callback((string s) =>
{
Trace.WriteLine(s);
});
LoadTextDocumentFilePaths();
}
private void LoadTextDocumentFilePaths()
{
// Add two real file paths to filePaths.
Assert.AreEqual(2, filePaths.Count);
}
[TestMethod]
public void DocumentChangedSavePromptTest()
{
// HOW DO I INJECT A MOCKED IMessageBoxService to `IDocumentController`?
// Open the documents internally.
var documents = documentProvider.GetDocumentViews(filePaths, mockProgress.Object);
Assert.AreEqual(2, documentProvider.DocumentControllerCache
.Count(d => d.GetType() == typeof(TextEditorController)));
// Ammend the text internally.
foreach (var d in documentProvider.DocumentControllerCache)
{
var controller = d.Key as TextEditorController;
}
// Need to finish writing the test.
}
}
所以我想知道如何将IMessageBoxService
类的IDocumentController
注入到[TestClass]
public class DocumentManagementTests
{
private Mock<IProgress<string>> mockProgress;
private Mock<IMessageBoxService> mockMessageBoxService;
private int messageBoxInvocationCounter = 0;
private List<string> filePaths = new List<string>();
[TestInitialize]
public void Initialize()
{
// Progress mock.
mockProgress = new Mock<IProgress<string>>();
mockProgress.Setup(m => m.Report(It.IsAny<string>()))
.Callback((string s) =>
{
Trace.WriteLine(s);
});
Assert.IsNotNull(mockProgress);
// Load the file paths.
LoadTextDocumentFilePaths();
}
private void LoadTextDocumentFilePaths()
{
string path = String.Empty;
string directory = Utils.GetAssemblyDirectory();
foreach (var fileName in new List<string>() { "DocumentA.txt", "DocumentB.txt" })
{
path = Path.Combine(directory, "Resources", "TextEditorDocs", fileName);
if (!File.Exists(path))
throw new IOException($"{path} does not exist");
filePaths.Add(path);
}
Assert.AreEqual(2, filePaths.Count);
}
[TestMethod]
public void DocumentChangedSavePrompt_OnUserClosing_Test()
{
// Message box service mock.
mockMessageBoxService = new Mock<IMessageBoxService>();
mockMessageBoxService
.Setup(m => m.DisplayMessage(It.IsAny<IWin32Window>(), It.IsAny<string>(), It.IsAny<string>(),
It.IsAny<MessageBoxButtons>(), It.IsAny<MessageBoxIcon>(), It.IsAny<MessageBoxDefaultButton>()))
.Returns((IWin32Window owner, string text,
string caption, MessageBoxButtons buttons, MessageBoxIcon icon,
MessageBoxDefaultButton defaultButton) => DialogResult.Cancel)
.Callback((IWin32Window owner, string text,
string caption, MessageBoxButtons buttons, MessageBoxIcon icon,
MessageBoxDefaultButton defaultButton) =>
{
Trace.WriteLine("MockMessageBoxService Invoked");
messageBoxInvocationCounter++;
});
Assert.IsNotNull(mockMessageBoxService);
// Open the documents.
List<TextEditorController> controllers = new List<TextEditorController>();
foreach (var path in filePaths)
{
TextEditorController controller = new TextEditorController(
CompositionRoot.Resolve<ITextEditorView>(),
mockMessageBoxService.Object);
Assert.IsNotNull(controller);
controllers.Add(controller);
TextEditorView view = (TextEditorView)controller.Open(path);
view.TextEditor.Text += "*";
Assert.IsTrue(controller.IsDirty);
}
// Test they are dirty and the message box is displayed.
foreach (var controller in controllers)
{
bool didClose = controller.TryClose(
new FormClosingEventArgs(CloseReason.UserClosing, false));
Assert.IsFalse(didClose);
}
Assert.AreEqual(2, messageBoxInvocationCounter);
}
}
类的ctor中?
感谢您的时间。
编辑。我提出的是以下测试方法。
TextEditorController
这是基于Stephen Ross的评论。我有什么理由不能创建具体的{{1}} s?