You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#的Moq框架中模拟Focus()方法?

解决Moq模拟Button.Focus()方法的问题

核心原因

WPF的Button.Focus()方法依赖实际UI渲染环境,测试环境中没有运行的UI线程和可视化树,无法实现真实的焦点效果。同时,UIElement.Focus()是public virtual方法,Moq可以拦截并验证它的调用,只是不会产生真实UI行为。

解决方案

1. 验证Focus()方法是否被调用(基础场景)

如果你的测试仅需确认代码逻辑确实触发了按钮焦点请求,无需真实焦点效果:

  • 创建Button的模拟对象并设置返回值:
    var mockButton = new Mock<Button>();
    // 模拟Focus()调用成功,返回true
    mockButton.Setup(b => b.Focus()).Returns(true);
    
  • 将模拟按钮注入到测试逻辑中(比如ViewModel关联的命令参数,或视图的控件引用)
  • 执行测试后验证调用次数:
    // 验证Focus()被调用一次
    mockButton.Verify(b => b.Focus(), Times.Once);
    

2. 抽象焦点操作(复杂视图场景)

如果是在XAML代码后置文件(xaml.cs)中直接调用SomeButton.Focus(),难以直接替换模拟按钮,建议通过接口抽象焦点操作:

  • 定义焦点操作接口:
    public interface IElementFocusHelper
    {
        bool Focus(UIElement targetElement);
    }
    
  • 实现生产环境的焦点助手:
    public class ElementFocusHelper : IElementFocusHelper
    {
        public bool Focus(UIElement targetElement)
        {
            return targetElement?.Focus() ?? false;
        }
    }
    
  • 在视图中注入该助手并替换原调用:
    // 构造函数注入助手
    private readonly IElementFocusHelper _focusHelper;
    public YourView(IElementFocusHelper focusHelper)
    {
        _focusHelper = focusHelper;
        InitializeComponent();
    }
    
    // 原代码 SomeButton.Focus(); 替换为:
    _focusHelper.Focus(SomeButton);
    
  • 测试时模拟助手并验证调用:
    var mockFocusHelper = new Mock<IElementFocusHelper>();
    mockFocusHelper.Setup(h => h.Focus(It.IsAny<UIElement>())).Returns(true);
    
    var view = new YourView(mockFocusHelper.Object);
    // 执行触发焦点操作的逻辑
    mockFocusHelper.Verify(h => h.Focus(It.Is<UIElement>(e => e == view.SomeButton)), Times.Once);
    

3. 处理Focus()返回值的依赖逻辑

如果你的代码依赖Focus()的返回值(比如根据是否成功获取焦点执行后续操作),直接通过Moq设置返回值即可:

// 模拟焦点获取失败的场景
mockButton.Setup(b => b.Focus()).Returns(false);

内容的提问来源于stack exchange,提问作者Durinko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:55:15