gpt4 book ai didi

unit-testing - 需要帮助使用 Messaging 在 MVVMLight 中编写单元测试用例

转载 作者:行者123 更新时间:2023-12-04 04:08:46 24 4
gpt4 key购买 nike

我对编写单元测试用例完全陌生。我在 WPF 中使用 MVVMLigh。是否有必要使用一些第三方测试框架或.Net 单元测试框架就足够了?另外如何处理单元测试用例中的静态类?在本例中为 AppMessages 类。

谁能指导我如何为以下代码编写单元案例:

public MyViewModel(Participant participant)
{
if (participant != null)
{
this.ParentModel = parentModel;
OkCommand = new RelayCommand(() => OkCommandExecute());
CalculateAmountCommand = new RelayCommand(() => CalculateAmount());
}
else
{
ExceptionLogger.Instance.LogException(Constants.ErrorMessages.FinancialLineCanNotBeNull, "FinancialLineViewModel");
AppMessages.DisplayDialogMessage.Send(Constants.ErrorMessages.FinancialLineCanNotBeNull, MessageBoxButton.OK, Constants.DefaultCaption, null);
}
}

public static class AppMessages
{
enum AppMessageTypes
{
FinancialLineViewDisplay,
FinancialLineViewClose,
DisplayDialogMessage
}

public static class DisplayDialogMessage
{
public static void Send(string message, MessageBoxButton button, string caption, System.Action<MessageBoxResult> action)
{
DialogMessage dialogMessage = new DialogMessage(message, action)
{
Button = button,
Caption = caption
};

Messenger.Default.Send(dialogMessage, AppMessageTypes.DisplayDialogMessage);
}

public static void Register(object recipient, System.Action<DialogMessage> action)
{
Messenger.Default.Register<DialogMessage>(recipient, AppMessageTypes.DisplayDialogMessage, action);
}
}
}

public class ExceptionLogger
{
private static ExceptionLogger _logger;
private static object _syncRoot = new object();

public static ExceptionLogger Instance
{
get
{
if (_logger == null)
{
lock (_syncRoot)
{
if (_logger == null)
{
_logger = new ExceptionLogger();
}
}
}

return _logger;
}
}

public void LogException(Exception exception, string additionalDetails)
{
LogException(exception.Message, additionalDetails);
}

public void LogException(string exceptionMessage, string additionalDetails)
{
MessageBox.Show(exceptionMessage);
}
}

最佳答案

关于可测试性

由于使用单例和静态类,MyViewModel 不可测试。单元测试是关于隔离的。如果你想对某些类(例如 MyViewModel)进行单元测试,你需要能够用 test double 替换它的依赖项。 (通常是 stub 或模拟)。只有当您在代码中提供接缝时,这种能力才会出现。用于提供接缝的最佳技术之一是依赖注入(inject)。学习 DI 的最佳资源是这本书,来自 Mark Seemann (Dependency Injection in .NET) .

您不能轻易地替换静态成员的调用。因此,如果您使用许多静态成员,那么您的设计并不完美。

当然,您可以使用不受约束的隔离框架,例如 Typemock Isolator、JustMock 或 Microsoft Fakes 来伪造静态方法调用,但它会花费金钱,并且不会插入您进行更好的设计。这些框架非常适合为遗留代码创建测试工具。

关于设计

  1. MyViewModel 的构造函数做的太多了。 Constructors should be simple .
  2. 如果依赖项为空,则构造函数必须抛出 ArgumentNullException 但不会静默记录错​​误。抛出异常清楚地表明您的对象不可用。

关于测试框架

您可以使用任何您喜欢的单元测试框架。即使是 MSTest,但我个人不推荐它。 NUnit 和 xUnit.net 要好得多。

进一步阅读

  1. Mark Seeman - Dependency Injection in .NET
  2. Roy Osherove - The Art of Unit Testing (2nd Edition)
  3. Michael Feathers - Working Effectively with Legacy Code
  4. Gerard Meszaros - xUnit Test Patterns

示例(使用 MvvmLight、NUnit 和 NSubstitute)

public class ViewModel : ViewModelBase
{
public ViewModel(IMessenger messenger)
{
if (messenger == null)
throw new ArgumentNullException("messenger");

MessengerInstance = messenger;
}

public void SendMessage()
{
MessengerInstance.Send(Messages.SomeMessage);
}
}

public static class Messages
{
public static readonly string SomeMessage = "SomeMessage";
}

public class ViewModelTests
{
private static ViewModel CreateViewModel(IMessenger messenger = null)
{
return new ViewModel(messenger ?? Substitute.For<IMessenger>());
}

[Test]
public void Constructor_WithNullMessenger_ExpectedThrowsArgumentNullException()
{
var exception = Assert.Throws<ArgumentNullException>(() => new ViewModel(null));
Assert.AreEqual("messenger", exception.ParamName);
}

[Test]
public void SendMessage_ExpectedSendSomeMessageThroughMessenger()
{
// Arrange
var messengerMock = Substitute.For<IMessenger>();
var viewModel = CreateViewModel(messengerMock);

// Act
viewModel.SendMessage();

// Assert
messengerMock.Received().Send(Messages.SomeMessage);
}
}

关于unit-testing - 需要帮助使用 Messaging 在 MVVMLight 中编写单元测试用例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17341469/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com