lundi 30 mars 2015

Moq does not subscribe to events in constructor

I am using Moq(4.2.1502.911) in my unit tests (xUnit). In a constructor, the object being constructed tries to subscribe to events of dependencies(arguments), but it does not seem to work.


The below code is an example to simulate the problem. Alarm class uses ICam interface dependency to alert when something moves.



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;
}
}


Below are unit tests.


First Test: In the constructor, Alarm object subscribes to ICam's event, but in unit test when I raise the event of the ICam mock object, Alarm's event is not raised.



[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
}


Second Test: Explicitly calls Subscribe method and the test passes.



[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
}


The problem seems to occur due to some kind of laziness at the initialization stage of mock objects but I am not sure about it.


Is there any solution or any other way to ensure event subscription?


Aucun commentaire:

Enregistrer un commentaire