消息框和单元测试
我正在尝试找到将消息框与我的逻辑分离的最佳方法,以便我可以正确地对其进行单元测试。现在我想知道如果我只创建一个单独的帮助器类(C#)是否就足够了,我可以稍后为我的消息框存根它。例如:
static class messageBoxHelper
{
public static void msgBoxAlg(string message, string title, MessageBoxButtons buttons, MessageBoxIcon icons, bool show)
{
if (show)
{
MessageBox.Show(message, title, buttons, icons);
}
}
然后每次我需要使用消息框时,我只需使用 messageboxHelper/msgBoxAlg(...) 而不是 messagebox.show(...)。使用 bool show 我可以在测试期间启用或禁用它。
我只是想知道这是否是“正确的方法”。我的意思是,有没有更简单或更好的方法来正确地做到这一点?我不能只是放弃消息框,它们向用户传递“重要”信息(“你想关闭这个窗口吗?”是/否等)。也可能是我没有使用正确的软件工程,我应该将我的消息框与我的业务逻辑更多地分离?
I'm trying to find the best way to uncouple messageboxes from my logic so I can properly unittest it. Now I was wondering if it would be enough if I just made a seperate helper class (C#) which I can stub later for my messagebox. For instance:
static class messageBoxHelper
{
public static void msgBoxAlg(string message, string title, MessageBoxButtons buttons, MessageBoxIcon icons, bool show)
{
if (show)
{
MessageBox.Show(message, title, buttons, icons);
}
}
Then everytime I'd need to use a messagebox i'd just use messageboxHelper/msgBoxAlg(...) instead of messagebox.show(...). Using the bool show I could enable or disable it during testing.
I'm just wondering if this is the "right way". By which I mean, is there an easier or better way to do this properly? I can't just ditch the messageboxes, they relay "vital" info to the user ("Do you want to close this windows?" YES/NO etc.). It could also just be I'm not using proper software engineering, and I should decouple my messageboxes from my bussinesslogic more?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
是的,这是正确的方法。但您应该实现
IDialogService
并将其注入到应显示对话框的类中,而不是静态类:在测试
SomeClass
期间,您应该注入IDialogService< 的模拟对象/code> 而不是真正的。
如果您需要测试更多 UI 逻辑,请考虑使用 MVVM 模式。
Yes, it is right way. But instead of static class, you should implement
IDialogService
and inject it into classes that should display dialogs:During testing the
SomeClass
you should inject mock object of theIDialogService
instead of real one.If you need to test more UI logic, consider to use MVVM pattern.
查看控制反转 (IoC),基本原理是执行操作等的事物应作为接口传入,然后使用 IoC 容器将接口绑定到应用程序的特定实现。为了在您的情况下轻松实现这一点,请将消息框作为接口传递,并在单元测试中创建该消息框服务的模拟(假)版本,该版本不显示消息框,
请查看 http://martinfowler.com/articles/injection.html 有关 IoC 的详细信息,我最喜欢的容器是 Ninject (http://ninject.org)
Look into Inversion of Control (IoC), the basic principal is that things that perform actions ect should be passed in as an interface then you use a IoC container to bind interfaces to specific implementations for your app. To easily achieve this in your case pass the thing that does message boxes in as an interface and in your unit test creat a mock (fake) version of that message box service which does not show a message box
look at http://martinfowler.com/articles/injection.html for details on IoC, my favorite container is Ninject (http://ninject.org)
理想情况下,您希望使用单元测试测试的代码是逻辑而不是 UI。因此,您的测试逻辑不应该真正显示消息框。如果您想测试 UI,那么我建议编码 UI 测试。
从你的问题来看,我想你的代码不应该真正使用
MessageBox
。也许可以考虑使用回调或任意Action
,或者 Luke McGregor 和 Sergey V 提到的方法。Ideally, you want the code your testing with Unit Tests to be logic and not UI. Therefore, the logic your testing shouldn't really be displaying a message box. If you are wanting to test the UI, then I would suggest Coded UI Tests.
Judging by your question, I would imagine your code shouldn't really be using a
MessageBox
. Perhaps instead consider using a callback or arbitraryAction
, or the approaches mentioned by Luke McGregor and Sergey V.“单元测试”,就其确切含义而言,是对原子行为的测试。这不是您可以为代码进行的唯一一种代码驱动测试。特别是对于使用您提到的“是/否”对话框测试较长的场景,更大规模的代码驱动测试通常比单元测试更有效。
然而,为了能够更容易地编写它们,最好不仅创建 Sergii 提到的特殊服务,而且使其调用异步:
通过将消息框包装在非异步服务调用中并模拟它们,时间更长在这种情况下,您将开始通过在实际发生之前预测用户操作(执行“Arrange”而不是“Act”)来矛盾“Arrange-Act-Assert”模式,这可能会在测试中导致许多问题,特别是如果您的测试是使用BDD/SpecFlow。使这些调用异步可以避免此类问题。有关消息框大规模测试的详细信息和示例,请参阅我的博客文章。
"Unit test", in its exact meaning, is a test of atomic behavior. This is not the only kind of code-driven tests you can make for your code. Especially for testing longer scenarios with "Yes/No" dialogs you mention, larger-scale code-driven tests are often more effective than unit tests.
However to be able to write them easier, it would be good not only to create a special service as it was mentioned by Sergii, but also to make its calls asynchronous:
By wrapping messageboxes in non-asynchronous service calls and mocking them, for longer scenarios you'll start to contradict "Arrange-Act-Assert" pattern by predicting user action before it actually happens (doing "Arrange" instead of "Act"), which can cause numerous problems in testing, especially if your tests are done using BDD/SpecFlow. Making these calls asynchronous allows to avoid such problems. See my blog article for details and samples of larger-scale tests with messageboxes.