如何使用NSubstitute模拟调用Dispatcher.BeginInvoke?

时间:2014-01-17 06:45:05

标签: mocking nsubstitute

在我的一个NSubstitute单元测试中,我有一个目标类。

我面临一个问题。类似于目标类中以下代码的情况:

public void _UpdateChecklistStatus(object checklistViewModel)
{
    OnCompletion<List<object>> updateChecklistStatusCallback = (result, ex) =>
    {
        if (result != null && result[0] != null && result[0] is bool)
        {
            Dispatcher.BeginInvoke(() =>
            {
                if (updateResult == false)
                {
                    //some code to execute
                }
            });
        }

        m_ObjectManager.UpdateDataAsync(
            new ChecklistDataModel(),
            OperationType.SaveSingle,
            new CacheSettings(),
            updateChecklistStatusCallback,
            updateChecklistStatuskParam,
            Constants.PROFILE_UPDATE_CHECKLIST_STATUS);
    };
}

我已经模拟了通过m_ObjectManager调用(异步)WCF服务的对象UpdateDataAsync,并使用有效结果回调回调updateChecklistStatusCallback,该结果也被模拟。

现在问题是在模拟m_ObjectManager.UpdateDataAsync之后,我将回调转换为updateChecklistStatusCallback,但Dispatcher.BeginInvoke中的代码永远不会被执行。

Dispatcher位于System.Windows.Threading

我在Dispatcher.BegingInvoke区块内的多个位置放置了断点,但没有一个被击中,单元测试成功完成。

有人可以帮我解决一下该怎么办?有没有办法嘲笑它或其他东西?

热切期待着回应!

谢谢,

要获得更清晰的信息,请粘贴实际代码:         [测试方法]         public void TestUpdatePriorityCommand()         {

        var res = new Dictionary<string, byte[]>();
        res.Add("Test", (new byte[] { 100, 150, 170, 200 }));

        var lstUpdateResObj = new List<object> { res };
        _target.StartDateTime = new DateTime(2014, 02, 20);
        _objManager.UpdateDataAsync(Arg.Any<ActivityModel>(), Arg.Is(OperationType.SaveSingle), Arg.Any<CacheSettings>(), Arg.InvokeDelegate<OnCompletion<List<object>>>(lstUpdateResObj, null), Arg.Any<ActivityUpdateParameters>(), Arg.Is(Constants.PROFILE_UPDATE_ACTIVITY_PRIORITY));
        _target.UpdatePriorityCommand.Execute("High");

        try
        {
            _objManager.ReceivedWithAnyArgs().UpdateDataAsync(Arg.Any<ActivityModel>(), Arg.Is(OperationType.SaveSingle), Arg.Any<CacheSettings>(), Arg.InvokeDelegate<OnCompletion<List<object>>>(lstUpdateResObj, null), Arg.Any<ActivityUpdateParameters>(), Arg.Is(Constants.PROFILE_UPDATE_ACTIVITY_PRIORITY));
        }
        catch (AmbiguousArgumentsException)
        {

            //throw;
        }
    }

执行测试后执行的方法:

    private void _UpdateActivityPriority(object parameter)
    {
        string oldPriority = m_Activity.Priority;

        if (IsSelected && !IsActivitySelectionEnabled)
        {
            MessageBoxResult msgBoxResult = MessageBox.Show(Utility.GetStringFromResource("ActivityListContainerViewModel_Edit_Launched_TaskAttributes"), Utility.GetStringFromResource("TasklistTitle"), MessageBoxButton.OKCancel);
            if (msgBoxResult == MessageBoxResult.OK)
            {
                //List<ActivityViewModel> lstActivityViewModel = new List<ActivityViewModel>() { this };
                //_UpdateSelectionList(lstActivityViewModel);
                //_LaunchActivityInSequence(lstActivityViewModel);
                HandleActivityNameClick.Execute(this);
            }
            _RefreshPriorityBasedUI();
            return;
        }

        //Check if reminder time is greater than the due time for the activity
        if (parameter != null && !string.IsNullOrEmpty(parameter.ToString()))
        {
            IDictionary<string, byte[]> updateRes;

            ActivityUpdateParameters parameters = new ActivityUpdateParameters
            {
                ActivityInstanceSer = ActivityInstanceSer,
                Priority = parameter.ToString(),
                UserResourceSer = m_ActivityListContext.LoggedInUser.SerialNo,
                Timestamp = m_Activity.Timestamp
            };


            OnCompletion<List<object>> myCallback = (result, ex) =>
            {
                if (ex != null)
                {
                    //Reset to old priority
                    m_Activity.Priority = oldPriority;
                    IsReminderUpdateRequired = false;

                    Dispatcher.BeginInvoke(new Action(() => Utility.HandleException(ex, "TasklistTitle", "_UpdateActivityPriority()", "ActivityViewModel", "UpdateActivityPriority", true, "Err_ActivityPriorityUpdate", true)));
                }
                else
                {
                    updateRes = (Dictionary<string, byte[]>)result[0];
                    Dispatcher.BeginInvoke(new Action(() =>
                                                     {
                                                         if (updateRes == null)
                                                         {
                                                             Utility.ShowMessage(Utility.GetStringFromResource("Err_ActivityPriorityUpdate"));

                                                             //Reset to old priority
                                                             m_Activity.Priority = oldPriority;
                                                             IsReminderUpdateRequired = false;
                                                         }
                                                         else
                                                         {
                                                             m_Activity.Priority = parameter.ToString();
                                                             ActivityData.Timestamp = new Dictionary<string, byte[]>(updateRes);
                                                         }
                                                         _RefreshPriorityBasedUI();
                                                     })
                    );
                }

                //Refresh UI based on the priority updates


                IsUpdatePriorityInProgress = m_ActivityListContext.IsWaitingForCallback = false;
            };

            m_ObjectManager.SecurityToken = Utility.Instance.SecurityToken;
            m_ObjectManager.ClientID = CLIENT_ID;
            try
            {
                IsUpdatePriorityInProgress = m_ActivityListContext.IsWaitingForCallback = true;

                m_ObjectManager.UpdateDataAsync(new ActivityModel(), OperationType.SaveSingle, new CacheSettings(), myCallback, parameters, Constants.PROFILE_UPDATE_ACTIVITY_PRIORITY);
            }
            catch (Exception ex)
            {
                IsUpdatePriorityInProgress = m_ActivityListContext.IsWaitingForCallback = false;

                Utility.HandleException(ex, "TasklistTitle", "_UpdateActivityPriority()", "ActivityViewModel", "UpdateActivityPriority", false, "Err_ActivityPriorityUpdate", true);
            }

        }

“OnCompletion”是我们自定义的“Action”回调函数,它是由于模拟而调用的。 但是“Dispatcher.BeginInvoke(new Action(()=&gt;”中的代码从未受到重创。

为简单起见,这里的伪代码更容易理解问题:

//Unit test Class
[TestMethod]
public void TestCommand()
{
    //callback mock here

    var parameter;

    //target is the object of the class which is to be tested
    //Command of the target executed here
    target.TestCommand.Execute(parameter); 
}



//This is a method in the target class
//Called as a result of command execution in the test method as above

private void calledMethod(object parameter)
{
        //ex is the exception that may be thrown by a service call
        //"OnCompletion" is our custom delegate of type "Action"
        OnCompletion<List<object>> myCallback = (result, ex) =>
        {
        if(ex==null)
        {
            Dispatcher.BeginInvoke(new Action(() =>
                                        {
                        //some code here
                        //Issue: execution never comes here
                         })             
        }
         }


    //WCF Service asynchronous Call
    //When the call completes, it calls the delegate "mycallback"

}

希望这次非常清楚。问题是回调委托“mycallback”被击中但“dispatcher.begininvoke”中的代码块从未执行。

0 个答案:

没有答案