I am using the Prism framework together with Moq. I am trying to verify that the AlarmService subscribes to an event in the constructor but I am getting an exception that this is not supported.
How else can I verify this?
This is my testMethod:
public void TestMethod()
{
var mockMachineDataService = new Mock<IMachineDataService<AlarmDto>>();
var mockAggregator = new Mock<IEventAggregator>();
var mockEvent = new Mock<MachineMessageReceivedEvent>();
mockAggregator.Setup(x => x.GetEvent<MachineMessageReceivedEvent>()).Returns(mockEvent.Object);
var alarmService = new AlarmService(mockAggregator.Object, mockMachineDataService.Object);
Assert.IsNotNull(alarmService);
mockAggregator.VerifyAll();
mockEvent.Verify(x => x.Subscribe(It.IsAny<Action<MachineMessage>>(), It.IsAny<ThreadOption>()));
}
When I am running this I get the following failure:
System.NotSupportedException: Invalid verify on a non-virtual (overridable in VB) member: x => x.Subscribe(It.IsAny<Action`1>(), It.IsAny<ThreadOption>())
I did have a look at this and split up the mockAggregator and mockEvent to get the above code, but it still fails.
I guess the problem was that the Subscribe method is overloaded and in the end calls another Subscribe method with more default options which is virtual. By changing the test to verify this virtual method I can verify that the subscribe method has been called.
[TestMethod]
public void TestConstructorSubscribesToMachineMessages()
{
var mockMachineDataService = new Mock<IMachineDataService<AlarmDto>>();
var mockAggregator = new Mock<IEventAggregator>();
var mockEvent = new Mock<MachineMessageReceivedEvent>();
mockAggregator.Setup(x => x.GetEvent<MachineMessageReceivedEvent>()).Returns(mockEvent.Object);
mockEvent.Setup(x => x.Subscribe(It.IsAny<Action<MachineMessage>>(), It.IsAny<ThreadOption>(), It.IsAny<bool>(), It.IsAny<Predicate<MachineMessage>>()));
var alarmService = new AlarmService(mockAggregator.Object, mockMachineDataService.Object);
Assert.IsNotNull(alarmService);
mockAggregator.VerifyAll();
mockEvent.VerifyAll();
}
You can only Mock/Verify a Virtual or an interface method. Looks like Subscribe is not a virtual method.
Moq (and few other frameworks) uses Castle Project's DynamicProxy to generate proxies on the fly at run-time so that members of an object can be intercepted without modifying the code of the class. That interception can only be done on public virtual and protected virtual methods.
See below URL for more information: http://www.castleproject.org/projects/dynamicproxy/
UPDATE: For the code that you can't modify you can use Shims available with Microsoft Fakes framework. Note: Its not a good practice to use Shims for your own code.
http://msdn.microsoft.com/en-us/library/hh549175.aspx
How can I verify that a Microsoft Fakes (beta) stub/shim was called (like AssertWasCalled in Rhino Mocks)?
Related
I have a simple hub that I am trying to write a test for with FakeItEasy and the verification of calling the client is not passing. I have the example working in a separate project that uses MOQ and XUnit.
public interface IScheduleHubClientContract
{
void UpdateToCheckedIn(string id);
}
public void UpdateToCheckedIn_Should_Broadcast_Id()
{
var hub = new ScheduleHub();
var clients = A.Fake<IHubCallerConnectionContext<dynamic>>();
var all = A.Fake<IScheduleHubClientContract>();
var id= "123456789";
hub.Clients = clients;
A.CallTo(() => all.UpdateToCheckedIn(A<string>.Ignored)).MustHaveHappened();
A.CallTo(() => clients.All).Returns(all);
hub.UpdateToCheckedIn(id);
}
I'm using Fixie as the Unit Test Framework and it reports:
FakeItEasy.ExpectationException:
Expected to find it once or more but no calls were made to the fake object.
The sample below works in XUnit & MOQ:
public interface IScheduleClientContract
{
void UpdateToCheckedIn(string id);
}
[Fact]
public void UpdateToCheckedIn_Should_Broadcast_Id()
{
var hub = new ScheduleHub();
var clients = new Mock<IHubCallerConnectionContext<dynamic>>();
var all = new Mock<IScheduleClientContract>();
hub.Clients = clients.Object;
all.Setup(m=>m.UpdateToCheckedIn(It.IsAny<string>())).Verifiable();
clients.Setup(m => m.All).Returns(all.Object);
hub.UpdateToCheckedIn("id");
all.VerifyAll();
}
I'm not sure what I've missed in the conversion?
You're doing some steps in a weird (it looks to me, without seeing the innards of your classes) order, and I believe that's the problem.
I think your key problem is that you're attempting to verify that all.UpdateToCheckedIn must have happened before even calling hub.UpdateToCheckedIn. (I don't know for sure that hub.UpdateToCheckedIn calls all.UpdateToCheckedIn, but it sounds reasonable.
There's another problem, where you configure clients.Setup to return all.Object, which happens after you assert the call to all.UpdateToCheckedIn. I'm not sure whether that's necessary or not, but thought I'd mention it.
The usual ordering is
arrange the fakes (and whatever else you need)
act, but exercising the system under test (hub)
assert that expected actions were taken on the fakes (or whatever other conditions you deem necessary for success)
I would have expected to see something more like
// Arrange the fakes
var all = A.Fake<IScheduleHubClientContract>();
var clients = A.Fake<IHubCallerConnectionContext<dynamic>>();
A.CallTo(() => clients.All).Returns(all); // if All has a getter, this could be clients.All = all
// … and arrange the system under test
var hub = new ScheduleHub();
hub.Clients = clients;
// Act, by exercising the system under test
var id = "123456789";
hub.UpdateToCheckedIn(id);
// Assert - verify that the expected calls were made to the Fakes
A.CallTo(() => all.UpdateToCheckedIn(A<string>.Ignored)).MustHaveHappened();
I'm trying to work out this whole testing thing, and have decided to start with an existing application that we use to record phone calls to the office. The app is a c#, mvvm, desktop application and for now at least, I'm just trying to work out how the testing framework operates. I have created a new test project, added reference to moq and am trying to run a test that verifies a method is called by another method.
The method I'm testing is simply a Command to close a window. The command uses messaging to communicate with a View Service to actually do the closing. Relevant code:
BaseViewModel:
public RelayCommand CloseWindowCommand { get; set; }
public BaseViewModel(IDataAccessService dataAccess)
{
...
CloseWindowCommand = new RelayCommand(CloseWindow);
}
internal virtual void CloseWindow()
{
SendCloseRequest();
}
void SendCloseRequest()
{
System.Windows.MessageBox.Show("called BaseVM.SendCloseRequest");
Messenger.Default.Send<RequestCloseMessage>(new RequestCloseMessage(this), this);
}
ViewService:
private Window CreateWindow(ViewModelBase vm)
{
...
window.DataContext = vm;
window.Closed += OnClosed;
// listen for the close event
Messenger.Default.Register<RequestCloseMessage>(window, vm, OnRequestClose);
return window;
}
public void OnRequestClose(RequestCloseMessage message)
{
System.Windows.MessageBox.Show("called ViewService.OnRequestClose");
var window = OpenedWindows.SingleOrDefault(w => w.DataContext == message.ViewModel);
if (window != null)
{
Messenger.Default.Unregister<RequestCloseMessage>(window, message.ViewModel, OnRequestClose);
if (message.DialogResult != null)
{
// trying to set the dialog result of the non-modal window will result in InvalidOperationException
window.DialogResult = message.DialogResult;
}
window.Close();
}
}
BaseViewModelTest (1):
[TestMethod]
public void SendCloseMesage_Calls_OnRequestClose()
{
Mock<IDataAccessService> mockProxy = new Mock<IDataAccessService>();
Mock<IViewService> mockView = new Mock<IViewService>();
var vm = new BaseViewModel(mockProxy.Object);
Mock<RequestCloseMessage> mockCloseMessage = new Mock<RequestCloseMessage>((ViewModelBase)vm, null);
vm.CloseWindowCommand.Execute(null);
mockView.Verify(v => v.OnRequestClose(mockCloseMessage.Object));
}
When I run the test it fails with:
Moq.MockException:
Expected invocation on the mock at least once, but was never performed: v => v.OnRequestClose
So, I tried to just test that the command calls the method in the VM:
BaseViewModelTest (2):
[TestMethod]
public void SendCloseMesage_Calls_CloseWindow()
{
Mock<IDataAccessService> mockProxy = new Mock<IDataAccessService>();
Mock<IViewService> mockView = new Mock<IViewService>();
//var vm = new BaseViewModel(mockProxy.Object);
Mock<BaseViewModel> mockVM = new Mock<BaseViewModel>(mockProxy);
Mock<RequestCloseMessage> mockCloseMessage = new Mock<RequestCloseMessage>((ViewModelBase)mockVM.Object, null);
mockVM.Object.CloseWindowCommand.Execute(null);
mockVM.Verify(vm => vm.CloseWindow());
}
This comes back with a similar error:
Moq.MockException:
Expected invocation on the mock at least once, but was never performed: vm => vm.CloseWindow()
However, in both cases, the System.Windows.MessageBox.Show("called <MethodName>"); statement is called as I have to deal with the dialog box. (I added the MessageBox commands for confirmation. The error is the same with or without them.)
Why is Moq telling me the method isn't called, when the MessageBox.Show() command in the method is being called?
PS: I'm not overly worried about whether testing the window closes is worth it, at the moment, I'm just trying to make sure I can test one method is calling another.
First of all, method MessageBox.Show is a static method. If you call it directly, Moq has no chance of knowing that.
In addition, do you even pass (or inject) your mockCloseMessage to your subject-under-test?
mockView.Verify(v => v.OnRequestClose(mockCloseMessage.Object));
This will verify that OnRequestClose was called at least once with the instance mockCloseMessage.Object, which seems not true in your case.
You should use It.IsAny<>() (or another mathing argument function, check the docs):
mockView.Verify(v => v.OnRequestClose(It.IsAny<RequestCloseMessage>()));
Update
After looking again at your code, there are some other points to mention:
The idea of mocking is when you would like to test a specific class that is dependent on other classes. Then, you would mock those dependencies classes in order to isolate and simplify your test.
It seems that you have created some mocks, but they are not injected to the object you are testing.
Another issue is that you have a dependency upon the Messenger class and a registration procedure has to be done, in order for the service to receive the event. You are mixing too much here, and make assumptions. To me, it seems that you are missing the whole point of unit test. Your test relies on actions that happens elsewhere.
Your code as is, doesn't seem easy to test.
I'm looking at the unit tests for SignalR and noticed one of the tests uses Moq to create a mock HubConnection:
[Fact]
public void HubCallbackClearedOnFailedInvocation()
{
var connection = new Mock<HubConnection>("http://foo");
var tcs = new TaskCompletionSource<object>();
tcs.TrySetCanceled();
connection.Setup(c => c.Send(It.IsAny<string>())).Returns(tcs.Task);
var hubProxy = new HubProxy(connection.Object, "foo");
var aggEx = Assert.Throws<AggregateException>(() => { hubProxy.Invoke("foo", "arg1").Wait(); });
var ex = aggEx.Unwrap();
Assert.IsType(typeof(TaskCanceledException), ex);
Assert.Equal(connection.Object._callbacks.Count, 0);
}
However, when I try and do the same with a slightly different mocking framework, RhinoMocks, it complains that the method isn't virtual:
[Test]
public void ShouldCreateBrokerWithHubConnection()
{
//Arrange
var url = "http://localhost6790";
var hubProxy = MockRepository.GenerateMock<IHubProxy>();
var hubConnection = MockRepository.GenerateMock<HubConnection>(url);
hubConnection.(c => c.CreateHubProxy("ArtemisClientHub")).Return(hubProxy);
... (more code)
}
System.InvalidOperationException : Invalid call, the last call has been used or no call has been made (make sure that you are calling a virtual (C#) / Overridable (VB) method).
Is this just a shortcoming of RhinoMocks compared to a newer library like Moq?
My tip is to use the none concrete types from your code and inject the concrete types using a Ioc. The signalr dot net client however is missing a DependencyResolver unlike the server. I rolled my own to get around this, you can check out the code here (But in your case you can use any Ioc like Ninject, autofac etc)
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/blob/master/SignalR.EventAggregatorProxy.Client.DotNet/Bootstrap/DependencyResolver.cs
The hub connection and proxy is a bit hard to abstract since you are dependent on the concrete types to create the proxy. I solved it with abstracting the creation of the hub proxy to a factory interface that returns a IHubProxy that can be easily mocked.
Look here
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy/blob/master/SignalR.EventAggregatorProxy.Client.DotNet/Bootstrap/Factories/HubProxyFactory.cs
All examples are taken from my dot net client for this library
https://github.com/AndersMalmgren/SignalR.EventAggregatorProxy
Coming from using Moq, I'm used to being able to Setup mocks as Verifiable. As you know, this is handy when you want to ensure your code under test actually called a method on a dependency.
e.g. in Moq:
// Set up the Moq mock to be verified
mockDependency.Setup(x => x.SomethingImportantToKnow()).Verifiable("Darn, this did not get called.");
target = new ClassUnderTest(mockDependency);
// Act on the object under test, using the mock dependency
target.DoThingsThatShouldUseTheDependency();
// Verify the mock was called.
mockDependency.Verify();
I've been using VS2012's "Fakes Framework" (for lack of knowing a better name for it), which is quite slick and I'm starting to prefer it to Moq, as it seems a bit more expressive and makes Shims easy. However, I can't figure out how to reproduce behavior similar to Moq's Verifiable/Verify implementation. I found the InstanceObserver property on the Stubs, which sounds like it might be what I want, but there's no documentation as of 9/4/12, and I'm not clear how to use it, if it's even the right thing.
Can anyone point me in the right direction on doing something like Moq Verifiable/Verify with VS2012's Fakes?
-- 9/5/12 Edit --
I realized a solution to the problem, but I'd still like to know if there's a built-in way to do it with VS2012 Fakes. I'll leave this open a little while for someone to claim if they can. Here's the basic idea I have (apologies if it doesn't compile).
[TestClass]
public class ClassUnderTestTests
{
private class Arrangements
{
public ClassUnderTest Target;
public bool SomethingImportantToKnowWasCalled = false; // Create a flag!
public Arrangements()
{
var mockDependency = new Fakes.StubIDependency // Fakes sweetness.
{
SomethingImportantToKnow = () => { SomethingImportantToKnowWasCalled = true; } // Set the flag!
}
Target = new ClassUnderTest(mockDependency);
}
}
[TestMethod]
public void DoThingThatShouldUseTheDependency_Condition_Result()
{
// arrange
var arrangements = new Arrangements();
// act
arrangements.Target.DoThingThatShouldUseTheDependency();
// assert
Assert.IsTrue(arrangements.SomethingImportantToKnowWasCalled); // Voila!
}
}
-- 9/5/12 End edit --
Since I've heard no better solutions, I'm calling the edits from 9/5/12 the best approach for now.
EDIT
Found the magic article that describes best practices. http://www.peterprovost.org/blog/2012/11/29/visual-studio-2012-fakes-part-3/
Although it might make sense in complex scenarios, you don't have to use a separate (Arrangements) class to store information about methods being called. Here is a simpler way of verifying that a method was called with Fakes, which stores the information in a local variable instead of a field of a separate class. Like your example it implies that ClassUnderTest calls a method of the IDependency interface.
[TestMethod]
public void DoThingThatShouldUseTheDependency_Condition_Result()
{
// arrange
bool dependencyCalled = false;
var dependency = new Fakes.StubIDependency()
{
DoStuff = () => dependencyCalled = true;
}
var target = new ClassUnderTest(dependency);
// act
target.DoStuff();
// assert
Assert.IsTrue(dependencyCalled);
}
Is there a way to attach a callback to every method of a mock without having setup each method? E.g.
var serviceMock = new Mock<IService>();
var count = 0;
//method does not exist, but you get the picture
serviceMock.CallbackAllMethods( () => { count++; throw new WebException()}; )
AutoFixture has nice integration with Moq and will automatically setup methods like this.
There's a good introduction here on Mark Seemann's blog.