Wpf 有没有更好的方法来测试这个不';不会导致偶尔的线程错误吗?

Wpf 有没有更好的方法来测试这个不';不会导致偶尔的线程错误吗?,wpf,unit-testing,mvvm,mvvm-light,Wpf,Unit Testing,Mvvm,Mvvm Light,我的viewmodel中有一个属性,其唯一任务是在属性更改时发送消息。我想进行单元测试,以确定它确实在做它的工作,所以我编写了以下测试 [TestFixture, RequiresSTA] public class ToolBarViewModelTests { private SecondaryScalingMode _SecondaryScalingMode; private void RecordSecondaryScalingSetting(SecondaryScali

我的viewmodel中有一个属性,其唯一任务是在属性更改时发送消息。我想进行单元测试,以确定它确实在做它的工作,所以我编写了以下测试

[TestFixture, RequiresSTA]
public class ToolBarViewModelTests
{
    private SecondaryScalingMode _SecondaryScalingMode;

    private void RecordSecondaryScalingSetting(SecondaryScalingMode obj)
    {
        _SecondaryScalingMode = obj;
    }

    [Test]
    public void AssertCombineAllCornersScalingMessageIsSent()
    {
        var vm = CreateNewToolBar();

        _SecondaryScalingMode = SecondaryScalingMode.IndividualCorner;

        AppMessages.SetSecondaryScalingMode.Register(this, (Action<SecondaryScalingMode>)RecordSecondaryScalingSetting);

        vm.CombineAllCornersScaling = true;
        Assert.IsFalse(vm.IndividualCornerScaling);
        Assert.IsFalse(vm.LeftRightScaling);
        Assert.IsFalse(vm.FrontRearScaling);
        Assert.IsTrue(vm.CombineAllCornersScaling);
        Assert.AreEqual(SecondaryScalingMode.CombineAllCorners, _SecondaryScalingMode);
    }
}

有没有更好的方法来编写此测试,以防止它以这种方式随机失败?

好的,这是我通常采用的方法。这和你做的很接近。 请记住,您还可以在单元测试中高举Messenger并订阅Messenger

我发布了您的代码的简化版本以匹配示例

我过去在单元测试中也有一些偶然的奇怪错误,这是一个时间/线程问题

为此,它帮助重置了Messenger foreach单元测试

这是viewmodel(简化的猜测工作=)…):

公共类UnitTestViewModel:ViewModelBase { 公共UnitTestViewModel() { Messenger.Default.Register(这是“SetSecondaryScalingMode”,(消息)=> { UpdateScalingMode(); }); } 私有布尔-鲁组合天线缩放; 公共布尔组合角缩放 { 得到{ 返回_combinealcornersscaling; } 设置{ _CombineAllCornersScaling=值; Send(“update”,“SetSecondaryScalingMode”); RaisePropertyChanged(“组合角缩放”); } } 私人住宅; 公共图书馆 { 得到 { 返回(u);; } 设置 { _单个角缩放=值; RaisePropertyChanged(“IndividualCornerScaling”); } } 私有布尔(u LeftRightScaling),; 公共布尔左向右缩放 { 得到 { 返回LeftRightScaling; } 设置 { _LeftRightScaling=值; RaisePropertyChanged(“LeftRightScaling”); } } 私人住宅; 公共图书馆 { 得到 { 返回_frontrealscaling; } 设置 { _FrontRearScaling=数值; RaisePropertyChanged(“前后缩放”); } } 私有void updateCalingMode() { 单个角标度=假; LeftRightScaling=false; FrontRearScaling=true; } } 这是单元测试(使用MSTest,但可以应用于其他包)

[TestMethod]
public void updaetsalingmode()
{
Messenger.Reset();
var vm=新的UnitTestViewModel();
bool updateMessageSend=false;
string _thiscanbetheobjectyouwerepassessing=string.Empty;
Messenger.Default.Register(vm,“SetSecondaryScalingMode”,(msg)=>
{
_这可以是您正在处理的对象=msg;
UpdateMessageSend=true;
});
vm.CombineAllCornersScaling=true;
Assert.AreEqual(true,updateMessageSend);
Assert.AreEqual(false,vm.IndividualCornerScaling);
AreEqual(false,vm.LeftRightScaling);
arenequal(true,vm.combinealCornersScaling);
Assert.AreEqual(“更新”,这可以是您正在处理的对象);
}
请记住,这是为了说明概念而简化的

我刚刚传递了一个消息负载字符串,但这可以是所有messenger功能所需要的复杂程度

我希望这有助于。。。另外,如果能看到ViewModel代码与另一种测试策略结合起来,那将是很有帮助的


附言:我还养成了一个习惯,每次测试只做一个断言,然后编写更多的测试…

我今天要出差,所以我必须稍后再尝试。
Test(s) failed. System.Reflection.TargetInvocationException : Exception has been thrown         by the target of an invocation.  
----> System.InvalidOperationException : The calling thread cannot access this object because a different thread owns it.  
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
public class UnitTestViewModel:ViewModelBase
{
    public UnitTestViewModel()
    {
        Messenger.Default.Register<string>(this, "SetSecondaryScalingMode", (message) =>
        {
            UpdateScalingMode();
        });
    }

    private bool _CombineAllCornersScaling;
    public bool CombineAllCornersScaling
    {
        get {
            return _CombineAllCornersScaling;
        }
        set {
            _CombineAllCornersScaling = value;
            Messenger.Default.Send<string>("update", "SetSecondaryScalingMode");
            RaisePropertyChanged("CombineAllCornersScaling");
        }
    }

    private bool _IndividualCornerScaling;
    public bool IndividualCornerScaling
    {
        get
        {
            return _IndividualCornerScaling;
        }
        set
        {
            _IndividualCornerScaling = value;

            RaisePropertyChanged("IndividualCornerScaling");
        }
    }

    private bool _LeftRightScaling;
    public bool LeftRightScaling
    {
        get
        {
            return _LeftRightScaling;
        }
        set
        {
            _LeftRightScaling = value;

            RaisePropertyChanged("LeftRightScaling");
        }
    }

    private bool _FrontRearScaling;
    public bool FrontRearScaling
    {
        get
        {
            return _FrontRearScaling;
        }
        set
        {
            _FrontRearScaling = value;

            RaisePropertyChanged("FrontRearScaling");
        }
    }

    private void UpdateScalingMode()
    {
        IndividualCornerScaling = false;
        LeftRightScaling = false;
        FrontRearScaling = true;
    }
}
 [TestMethod]
   public void UpdaetScalingMode()
   {
       Messenger.Reset();
       var vm = new UnitTestViewModel();
       bool updateMessageWasSend = false;
       string _thisCanBeTheObjectYouWerePassing = String.Empty;
       Messenger.Default.Register<string>(vm, "SetSecondaryScalingMode", (msg) =>
       {
           _thisCanBeTheObjectYouWerePassing = msg;
           updateMessageWasSend = true;
       });

       vm.CombineAllCornersScaling = true;

       Assert.AreEqual(true, updateMessageWasSend);
       Assert.AreEqual(false, vm.IndividualCornerScaling);
       Assert.AreEqual(false, vm.LeftRightScaling);
       Assert.AreEqual(true, vm.CombineAllCornersScaling);
       Assert.AreEqual("update", _thisCanBeTheObjectYouWerePassing);

   }