Max*_*com 3 static-methods unit-testing testcase mvvm-light
我是单元测试用例写作的新手.我在WPF中使用MVVMLigh.是否有必要使用一些第三方测试框架或.Net Unit测试框架呢?另外如何在单元测试用例中处理静态类?在这种情况下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);
}
}
Run Code Online (Sandbox Code Playgroud)
关于可测试性
由于使用单例和静态类MyViewModel是不可测试的.单元测试是关于隔离的.如果要对某些类(例如,MyViewModel)进行单元测试,则需要能够通过test double(通常是stub或mock)替换其依赖项.只有在代码中提供接缝时才会出现此功能.用于提供接缝的最佳技术之一是依赖注入.学习DI的最佳资源是Mark Seemann(.NET中的依赖注入)这本书.
您无法轻易替换静态成员的调用.因此,如果您使用许多静态成员,那么您的设计并不完美.
当然,您可以使用无约束隔离框架(如Typemock Isolator,JustMock或Microsoft Fakes)来伪造静态方法调用,但这需要花钱,而且不会让您更好地设计.这些框架非常适合为遗留代码创建测试工具.
关于设计
关于测试框架
您可以使用任何您喜欢的单元测试框架.即使是MSTest,但我个人并不推荐它.NUnit和xUnit.net好多了.
进一步阅读
样本(使用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);
}
}
Run Code Online (Sandbox Code Playgroud)