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.
Related
I have a simple functional style test for output of a command that I've written using Mediatr's IRequest and IRequestHandler<>
[Fact]
public void TestReturnValuesAsync()
{
// Arrange
var handler = new Mock<IRequestHandler<SyncSubmerchantDataCommand, CommandResult<int>>>();
handler.Setup(x => x.Handle(It.IsAny<SyncSubmerchantDataCommand>(), It.IsAny<CancellationToken>())).ReturnsAsync(new CommandResult<int>(0, ResultStatus.Success, "string"));
// Act
var result = handler.Object.Handle(new SyncSubmerchantDataCommand(), new CancellationToken());
// Assert
result.Result.Data.ShouldBe(0);
result.Result.Status.ShouldBe(ResultStatus.Success);
result.Result.Message.ShouldBe("string");
}
Since this command runs as a background task, I don't want it interrupted. I have a variable, submerchantList, that is of type List<T> which is used in a foreach loop to do work. The work is set in a try-catch because I don't want the command interrupted, as I stated before. I want to test the output of the what is written to my logs (_log.info) if an exception is thrown during this process.
public class CommandNameHandler : IRequestHandler<source, destination> {
// constructors and privates
public async destination Handle(param, token)
{
var submerchantList = db call.ToList();
foreach (var item in submerchantList)
{
try {
//does work
}
catch (Exception e) {
if (item != null)
_log.info($"{e} - {item.Id}");
}
return some out put
}
The problem is that I can't seem to figure out how to set the value of the any variable, such as the submerchantList within the Handle in order to throw the exception for my next test. I'm stumped.
Any help would be greatly appreciated.
SOLUTION:
Here was the solution: Stubbing the database call by injecting an in-memory DbSet. I used this resource learn.microsoft.com/en-us/ef/ef6/fundamentals/testing/… This issue was db call.ToList It looked something like this _db.Table.Include(x => x.Foreign).Where(x => x.Foreign.Field == Enum.Value).ToListAsync() While I was setting up the Mock DbSet, I had to use the string version, not the LINQ-chain version in the unit test. So, that means mockDbset.Setup(x => x.Table.Include("Foreign")).Returns(myCustomDbSet); Hope that helps someone!
It is possible to test if a method has been called using Moq and dependency injection. However, is it possible to test if one method in a class calls another within the same class?
For example, I want to test that if I log a certain exception, that an information message is logged as well.
The method is:
public void Error(string message, Exception exception, long logId = 0)
{
var int32 = (int)logId;
Info("Id was converted to an int so that it would fit in the log: " + logId, int32);
Error(message, exception, int32);
}
This was my attempt at unit testing it. The test fails, is there any way that it can it be done?
void logging_an_error_with_a_long_id_also_logs_info()
{
var mock = new Mock<ILogger>();
var testedClass = new Logger();
var counter = 0;
testedClass.Error("test" + counter++, new Exception("test" + counter), Int64.MaxValue);
mock.Verify(m => m.Info(It.IsAny<string>(), It.IsAny<int>()));
}
Since the Info and Error methods are in the same class (ClassA), I don't believe I can pass ClassA as a dependency into ClassA. So does it not need tested?
The best you're going to be able to do is to make Info virtual. This will allow you to create a Mock<Logger>, set CallBase = true, and verify that Info was called.
var mock = new Mock<Logger>
{
CallBase = true
};
mock.Object.Error("test" + counter++, new Exception("test" + counter), Int64.MaxValue);
mock.Verify(m => m.Info(It.IsAny<string>(), It.IsAny<int>()));
This way, you're still calling the actual implementation of Error, but you've used Moq to verify the Info method was called.
It feels like you're trying to test the wrong thing. It's not really important that the Info method on your class is called from the Error method, what's important is that the behaviour of the Info method occurs. How it happens is an implementation detail of the class.
If I had a math class with two functions:
public int Mult(int x, int y) {
return x*y;
}
public int Sqr(int x) {
return Mult(x,y);
}
I wouldn't test that calling Sqr called out to the Mult function, I would test Sqr(4)==16. It doesn't matter if that calculation takes place in the Sqr method, or in another method of the class.
Whilst #Andrew's solution is probably what you're after, mocking the class you're testing tends to lead to tightly coupled, brittle tests.
If it's impractical to test the call by observing it's side effects, then it may be a sign that the implementation could use a bit of refactoring.
I ran into a strange problem today - I was writing a unit test around a SIM object. It asserts that when the SIM object is updated and the PIN attempts remaining has changed, it will call a particular method. The test looks like this:
[Test]
public void TestUpdateSimInfoWithPinAttemptsChangedCallsOnPinAttemptsRemaining()
{
var info = new SimPinInfo {PinAttemptsRemaining = 10};
var sim = new Mock<Sim>(info);
info.PinAttemptsRemaining = 2;
sim.Object.UpdateSimInfo(info);
sim.Verify(s => s.FireOnPinAttemptsRemaining(), Times.Once());
}
So the mock SIM object is created with 10 PIN attempts remaining. The SimPinInfo object then has the PinAttemptsRemaining value reduced to 2 before being passed to the UpdateSimInfo() method.
SIM constructor (trimmed for clarity):
internal Sim(SimPinInfo info) : this()
{
_pinAttemptsRemaining = info.PinAttemptsRemaining;
_pukAttemptsRemaining = info.PukAttemptsRemaining;
......
}
And the UpdateSimInfo() method (trimmed):
internal void UpdateSimInfo(SimPinInfo info)
{
lock(_locker)
{
if (_pinAttemptsRemaining != info.PinAttemptsRemaining)
{
Log("PinAttemptsRemaining changed");
_pinAttemptsRemaining = info.PinAttemptsRemaining;
FireOnPinAttemptsRemaining();
}
.....
}
}
A pretty simple test - what should happen is the above if statement will be true (pin attempts remaining has changed) so the OnPinAttemptsRemaining event will be fired. However, the test failed (although not all the time - it passed when I slowly stepped through the code!). What was happening was the if statement was false - both _pinAttemptsRemaining and info.PinAttemptsRemaining were 2. It appears that the SIM mock is not actually created when expected - when the info.PinAttemptsRemaining was 10.
To demonstrated this, I added a comment:
var sim = new Mock<Sim>(info);
info.PinAttemptsRemaining = 2;
Console.WriteLine("SIM's pin attempts = " + sim.Object.PinAttemptsRemaining);
I also put a breakpoint in the SIM object's constructor. The breakpoint was hit when stepping over the Console.WriteLine line, not the new Mock... line. So the object is not being created until needed.
I believe this is called lazy-loading or lazy-evaluation.
There were various workaround to this behaviour - I ended up creating a new SimPinInfo object to pass to UpdateSimInfo().
Has anyone come across this behaviour before? I couldn't find any references to it.
From what I've read you're trying to test a Mock.
sim.Object.UpdateSimInfo(info);
Mocks are meant to substitute dependencies, you don't use them to substitute the code you mean to test. Without seeing the whole code, I'd guess that you don't even need a Mock to test this behaviour. Assuming that FireOnPinAttemptsRemaining raises an event I'd recommend something like this for a test method:
[Test]
public void TestUpdateSimInfoWithPinAttemptsChangedCallsOnPinAttemptsRemaining()
{
int eventFiredCount = 0;
var info = new SimPinInfo {PinAttemptsRemaining = 10};
var sim = Sim(info);
sim.OnPinAttemptsRemaining += (sender, e) => { eventFiredCount++; };
info.PinAttemptsRemaining = 2;
sim.UpdateSimInfo(info);
Assert.AreEqual(1, eventFiredCount);
}
I'm not 100% on the event handler since I don't know the Fire method is raising an event or not, or the event name, but it should give you an idea.
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);
}
I'm trying to become more familiar with the Rhinomocks framework, and I'm trying to understand the Expect methods of rhinomocks.
Here's a unit test I have written:
[TestMethod]
public void Create_ValidModelData_CreatesNewEventObjectWithGivenSlugId()
{
//Arrange
var eventList = new List<Event>() { new Event() { Slug = "test-user" } };
_stubbedEventRepository.Stub(x => x.GetEvents())
.Return(eventList);
_stubbedEventRepository
.Expect(x => x.SaveEvent(eventList.SingleOrDefault()))
.Repeat
.Once();
var controller = new EventController(_stubbedEventRepository);
EventViewModel model = new EventViewModel();
//Act
//controller.Create(model); COMMENTED OUT
//Assert
_stubbedEventRepository.VerifyAllExpectations();
}
I thought I understood this code to only pass if the SaveEvent(...) method get's called exactly once. However, with controller.Create(model) commented out, the test still passes. Inside controller.Create(model) is where the SaveEvent() method gets called.
I tried the following:
_stubbedEventRepository
.Expect(x => x.SaveEvent(eventList.SingleOrDefault()));
But it still passes every time, so what am I doing incorrectly stack overflow? The sources I have looked at online haven't been able to help me. Why is VerifyAllExpectations() yielding a successful unit test?
Thank you!
Here's the body of the controller constructor:
public EventController(IEventRepository eventRepository)
{
_eventRepository = eventRepository;
}
edit:
// member variables
private IEventRepository _stubbedEventRepository;
[TestInitialize]
public void SetupTests()
{
_stubbedEventRepository = MockRepository.GenerateStub<IEventRepository>();
}
If you want to verify the behavior of the code under test, you will use a mock with the appropriate expectation, and verify that. If you want just to pass a value that may need to act in a certain way, but isn't the focus of this test, you will use a stub.