【问题标题】:Moq does not subscribe to events in constructorMoq 不订阅构造函数中的事件
【发布时间】:2015-03-30 10:15:47
【问题描述】:

我在单元测试 (xUnit) 中使用 Moq(4.2.1502.911)。在构造函数中,正在构造的对象尝试订阅依赖项(参数)的事件,但它似乎不起作用。

以下代码是模拟问题的示例。警报类使用 ICam 接口依赖项在有东西移动时发出警报。

public interface ICam
{
    event EventHandler VisualDetected;
}

public class Alarm : ICam
{
    private ICam _cam;

    public Alarm(ICam cam)
    {
        _cam = cam;

        // Subscribe to forward events, DOES NOT WORK
        _cam.VisualDetected += VisualDetected;
    }

    public event EventHandler VisualDetected;

    // If I call this method explicitly, test succeeds
    public void Subscribe()
    {
        // Subscribe to forward events outside the constructor
        _cam.VisualDetected += VisualDetected;
    }
}

以下是单元测试。

第一次测试:在构造函数中,Alarm 对象订阅了 ICam 的事件,但是在单元测试中,当我引发 ICam 模拟对象的事件时,没有引发警报的事件。强>

    [Fact]
    public void Alarm_SubscribesInCtor()
    {
        var cam = new Mock<ICam>();
        var alarm = new Alarm(cam.Object);
        var raised = false;
        alarm.VisualDetected += (o, e) => raised = true;

        cam.Raise(c => c.VisualDetected += null, new EventArgs());

        Assert.True(raised); // FAILS
    }

第二次测试:显式调用订阅方法,测试通过。

    [Fact]
    public void Alarm_SubscribesOutsideCtor()
    {
        var cam = new Mock<ICam>();
        var alarm = new Alarm(cam.Object);
        var raised = false;
        alarm.VisualDetected += (o, e) => raised = true;
        alarm.Subscribe();

        cam.Raise(c => c.VisualDetected += null, new EventArgs());

        Assert.True(raised); // SUCCEEDS
    }

这个问题似乎是由于模拟对象初始化阶段的某种惰性而发生的,但我不确定。

有什么解决方案或者其他方式可以保证事件订阅吗?

【问题讨论】:

    标签: c# unit-testing events moq xunit


    【解决方案1】:

    问题不在于起订量,问题在于您的代码:

    _cam.VisualDetected += VisualDetected;
    

    在这里,您添加来自thisVisualDetected 事件的所有代表,并将它们附加到_camVisualDetected 事件。

    您的问题是,此时,VisualDetectedthis 事件没有附加任何代表,因此 _cam.VisualDetected 没有添加任何代表。

    稍后向alarm.VisualDetected 添加处理程序不会影响_cam.VisualDetected(并且不会向其中添加该处理程序)。

    如果您想“转发”事件,您可以简单地将处理程序附加到调用this.VisualDetected_cam.VisualDetected

    public Alarm(ICam cam)
    {
        _cam = cam;
    
        _cam.VisualDetected += (s, e) =>  
        {
            if(VisualDetected != null) 
                VisualDetected(this, e);
        };
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多