Moq fake one method but use real implementation of another - c#

Given an interface IService that has Method1() and Method2().
I want to test that when Method1() throws an Exception, Method2() is called and returns a given value.
(Method2() is called when Method1() throws).
Therefore I need to test a real Method2() with a fake Method1(), they are methods of the same interface.
Here is my test code:
MBase sut.MethodX() is the only entry point. It uses IService.
My aim is to assert that Method2() returns something.
// Arrange
// Fake bytes in.
var networkStreamMock = new Mock<INetworkStream>();
networkStreamMock.Method1(x => x.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>())).Returns(It.IsAny<byte[]>());
// Force throw TimeoutException.
var mock = new Mock<IService>();
mock.Setup(x => x.Method1(new Message
{
Xml = Xml,
}
)).Throws<TimeoutException>();
// Check Method 2 is called. (this is done in its own test so commented out)
// mock.Setup(m => m.Method2(It.IsAny<Message>())).Verifiable();
// New MBase.
IKernel kernel = new StandardKernel(new FakeBindings());
kernel.Rebind<IService>().ToConstant(mock.Object);
MBase sut = kernel.Get<M>();
// Act
sut.MethodX(networkStreamMock.Object);
// Here I would like to assert on the return value of Method2
mock.Verify(m => m.Method2(It.IsAny<Message>()));
Is this possible with Moq or another mocking framework? How do I do it?
I can create a manual mock with a fake implementation of Method1() and a real implementation of Method2() but I wonder if there is a better approach.
I have already tested IService in isolation but I now wish to test it's interaction with MBase.

You can do this with:
var mock = new Mock<MyNetworkStream>(){ CallBase = true };
mock.Setup(m => m.Method1....
The above code will use the real implementation of MyNetworkStream for any method/property which is not explicitly setup. I.e. it'll call the real Method2(), while the Method1() will be the mocked version.
CallBase=true is usually meant to test abstract classes (if this is right or wrong, is out of the scope of this question).

In this case (unless there's a lot more going on) I would just create my own test class extending the class with the real behavior, that implements the interface you need to mock. This way you can mock the one value, and fallback to the base class for the real functionality.

Related

Difficulties mocking ILogger and verifying method calls

I'm trying to test that one of my controller end points calls the LogError once. This is the test:
[Fact]
public void Log_error_should_call_logger_error_method()
{
//Arrange
var applicationException = new ApplicationException("This is a mocked exception");
var exceptionHandlerFeatureMock = ErrorsControllerGenerator.GenerateExceptionHandlerFeatureMock(applicationException);
Mock<ILogger<ErrorsController>> iLoggerMock = new Mock<ILogger<ErrorsController>>();
var sut = ErrorsControllerGenerator.GenerateErrorsController(exceptionHandlerFeatureMock, iLoggerMock);
//Act
sut.LogError("This is a test error");
//Assert
iLoggerMock.Verify(x => x.LogError("This is a test error"), Times.Once());
}
I'm receiving the following error when running the test:
System.NotSupportedException : Invalid verify on a non-virtual (overridable in VB) member: x => x.LogError("This is a test error", new[] { })
I'm slightly confused by this as from what I understand, this shouldn't happen because I'm mocking the interface rather than the concrete implementation? If I was to use the concrete logger class, I know that the method would have to be marked as virtual for this to work but I didn't think that was the case when using interfaces.
I've tried adding this line to the //Arrange part of the test:
iLoggerMock.Setup(x => x.LogError(It.IsAny<string>())).Verifiable();
But this just throws this error instead:
System.NotSupportedException : Expression references a method that does not belong to the mocked object: x => x.LogError(It.IsAny<String>(), new[] { })
This also confuses me as the mocked object (ILogger) does have a LogError method
You can't mock logger methods such as LogError because unfortunately they are extension methods and are not defined in the ILogger interface.
Instead of trying to verify whether the relevant log methods were called, perhaps you could verify the executed code takes the expected path i.e. the path where the relevant log methods would be called.

How much do moq mock objects resemble the actual classes?

I'm new to unit tests and mocking. So please don't roast me :)
I wrote my first very simple unit test and it seems to work. But tbh I'm not getting what's going on. What I'm trying to test is, that the showDialog method is called with an argument of type EditViewModel when the OpenEditView() method of the main window is called. I'm using a dialog service to make my code satisfy the MVVM design pattern. And I'm using a factory to not directly create an object of a view model class directly in the method I want to test. The factory just creates and returns the object in asking it for.
When run, the test is passed.
How can this happen if I don't setup the CreateEditViewModel method of the ViewModelFactoryMock? What exactly is returned by the method when its called during the test? Or in a broader sense: How much do mocked objects resemble the actual object? When do I need to setup the methods of mocked objects?
vm.OpenEditView()
public void OpenEditView()
{
EditViewModel viewModel = viewModelFactory.CreateEditViewModel(Argument1, Argument2, ...);
bool? result = dialogService.ShowDialog(viewModel);
}
Unit Test:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
// Arrange
var DialogServiceMock = new Mock<IDialogService>();
var ViewModelFactoryMock = new Mock<IViewModelFactory>();
DialogServiceMock
.Setup(x => x.ShowDialog(It.IsAny<EditViewModel>()))
.Returns(true)
.Verifiable();
MainWindowViewModel vm = new MainWindowViewModel(DialogServiceMock.Object, ViewModelFactoryMock.Object);
// Act
vm.OpenEditView();
// Assert
DialogServiceMock.Verify(mock => mock.ShowDialog(It.IsAny<EditViewModel>()));
}
}
IViewModelFactory
public interface IViewModelFactory
{
EditViewModel CreateEditViewModel(Argument1, Argument2, ...);
}
How can this happen if I don't setup the CreateEditViewModel method of the ViewModelFactoryMock?
You do not actually do anything with what is returned from the mock so there was no opportunity for it to fail because the value was null.
What exactly is returned by the method when its called during the test?
In this case the value of viewModel is null because no expectation was setup on the mock.
The test passes because the verification
DialogServiceMock.Verify(mock => mock.ShowDialog(It.IsAny<EditViewModel>()));
expects It.IsAny<EditViewModel>() which can include null.
If you wanted to verify the actual instance, then you can create one and setup the mock to behave as expected. Assuming EditViewModel is not sealed
[TestMethod]
public void TestMethod1()
{
// Arrange
var DialogServiceMock = new Mock<IDialogService>();
var ViewModelFactoryMock = new Mock<IViewModelFactory>();
var viewModel = Mock.Of<EditViewModel>(); // Or new EditViewModel(...);
ViewModelFactoryMock
.Setup(_ => _.CreateEditViewModel(It.IsAny<Argument1>(),....));
.Returns(viewModel);
DialogServiceMock
.Setup(x => x.ShowDialog(It.IsAny<EditViewModel>()))
.Returns(true)
.Verifiable();
MainWindowViewModel vm = new MainWindowViewModel(DialogServiceMock.Object, ViewModelFactoryMock.Object);
// Act
vm.OpenEditView();
// Assert
//verify that the mocked view model was actually used.
DialogServiceMock.Verify(mock => mock.ShowDialog(viewModel));
}
How much do mocked objects resemble the actual object?
They (the mocks) are derived from the base type so they are implementations of the actual object/interface
When do I need to setup the methods of mocked objects?
Only when their behavior is needed to exercise the test to completion.
How much do mocked objects resemble the actual object?
None much rather it's a mocked setup. MOQ is a Dynamic Proxy based based mocking system. So when you create a mock(Stub) of the interface (interface whose api you want to mock) it creates a proxy of that interface, in broad, it creates a proxy class by inheriting the actual type/interface under mock and override the specific method (That's why MOQ can only work with virtual or abstract method).
Thus when the actual api method gets called, your test runner make sure to call the interceptor method (Setup method) with any argument you pass and not with an actual argument.

Moq is making method call and returning real data, and not the return data in Setup

I am trying to return a statically declared array of NWatchNativeNode[], but Moq seems to actually be calling the real method that goes to the gets the real system data. Is the Setup in the below incorrect?
I want to make sure that when
GetNodesInCriticalCondition() is called, criticalNodes1 is returned.
Unit Test Code
var criticalNodes1 = new NWatchNativeNode[]
{
factory.CreateNativeNode(NWatchNodeType.NetworkSwitch,
"MySwitch",
"MyAlias",
12345
),
factory.CreateNativeNode(NWatchNodeType.NetworkSwitch,
"MySwitch2",
"MyAlias2",
54321
),
};
var mock = new Mock<NWatchCasModelStatusScheduleEntry>(_application);
mock.Setup(x => x.GetNodesInCriticalCondition()).Returns(criticalNodes1);
var nodes = mock.Object.GetNodesInCriticalCondition();
Assert.AreEqual(2, nodes.Length); // This should return true
The most likely reason that the Mock returns the real system data is that your method GetNodesInCriticalCondition() is not declared virtual.
In order for Moq to be able to setup the method calls, these methods have to be virtual, otherwise it cannot overwrite them and hence cannot intercept them, which results in the original method being called.
Edit:
If your method is internal, you have to give access to it to your Unit Test project and to Moq.
You can do this by adding
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] and
[assembly: InternalsVisibleTo("TestProjectNameSpace")]
to the AssemblyInfo.cs file of the project you are creating mocks for.
As per your request, here is a quick example of how to test with Moq.
Let us make some classes and interfaces to test to start with.
public interface IFoo
{
IEnumerable<int> GetFoos();
}
public class Foo : IFoo
{
public IEnumerable<int> GetFoos()
{
return Enumerable.Range(1, 10);
}
}
public class Bar
{
private readonly IFoo foo;
public Bar(IFoo foo)
{
this.foo = foo;
}
public IEnumerable<int> SquareFoos()
{
foreach(var item in foo.GetFoos())
{
yield return item * item;
}
}
}
Now, Bar has a dependency on the IFoo interface. Now we want to test the functionality of SquareFoos on the Bar class. This is our subject under test. What we want to mock is the IFoo interface passed to the constructor of Bar. This gives us the following unit test setup.
// Arrange
var mock = new Mock<IFoo>();
mock.Setup(m => m.GetFoos()).Returns(Enumerable.Range(1, 2));
var sut = new Bar(mock.Object);
// Act
var results = sut.SquareFoos().ToList();
// Assert
Assert.AreEqual(2, results.Count);
In this case we mock out what GetFoos returns to allow us to test our Bar class.

How can I add an Expression<Action<T>> as an interception to a faked object?

Is there an alternative way to intercept method calls in FakeItEasy if the method and arguments are already represented as an Expression<Action<T>>?
Normally I would simply use
IFoo foo = A.Fake<IFoo>();
A.CallTo(() => foo.SomeMethod("SomeString", A<Exception>.Ignored)).Invokes( ... );
But in my current situation I have a fake IFoo and an Expression<Action<IFoo>> and am trying to marry the two together.
This is actually existing Moq code that I'm re-writing for FakeIEasy but I'm not sure whether it's possible. The Moq version of this is
private void ExampleMoqMethod(Expression<Action<IFoo>> setupAction)
{
Mock<IFoo> Mock = new Mock<IFoo>();
Mock.Setup(setupAction).Callback( ... );
}
I tried the obvious (below) but got a "The specified object is not recognized as a fake object" error (I suspect because the fake object is not being referred to at all!)
private void ExampleFIEMethod(Expression<Action<IFoo>> callSpecification)
{
IFoo foo = A.Fake<IFoo>();
A.CallTo(callSpecification).Invokes( ... );
}
I would hazard a guess that this is possible by implementing IFakeObjectCallRule and using Fake.GetFakeManager(foo).AddRuleFirst(customRule) but I was wondering if there was a more straightforward way doing this?

How to write nUnit/Moq for testing generic extension methods?

I have the following generic extension method for deleting all EntityObjects from an ObjectContext
public static void DeleleAllObjects<TEntity>(this ObjectContext context)
where TEntity : EntityObject
{
var objectSet = context.CreateObjectSet<TEntity>();
objectSet.ToList().ForEach(e => objectSet.DeleteObject(e));
}
I'm fairly new to TDD and using nUnit/Moq...but I'm not sure where to being to write tests for this method?
I hope this helps:
[TestFixture]
public class ExtensionTest
{
public class FakeEntity : EntityObject
{
}
[Test]
public void DeleteAllObjects()
{
//arrange
var objectsToDelete = new List<FakeEntity>
{
new FakeEntity(),
new FakeEntity()
};
var mockContext = new Mock<ObjectContext>();
var mockObjectSet = new Mock<ObjectSet<FakeEntity>>();
mockObjectSet.Setup(x => x.ToList()).Returns(objectsToDelete);
mockContext.Setup(x => x.CreateObjectSet<FakeEntity>()).Returns(mockObjectSet.Object);
//act
mockContext.Object.DeleteAllObjects<FakeEntity>();
//assert
mockContext.Verify(x => x.CreateObjectSet<FakeEntity>(), Times.Once());
mockObjectSet.Verify(x => x.ToList(), Times.Once());
mockObjectSet.Verify(x => x.DeleteObject(It.IsAny<FakeEntity>()), Times.Exactly(2));
}
}
Now, this is assuming all your mocked types (the context and the object set) have the methods you invoke declared as virtual or the classes are abstract. Mocking interfaces is usually less restrictive.
Also, if you want to get more picky with your asserts to ensure that indeed DeleteObject is called first with the first instance, and then with the second, and not twice on the first, then you could change that part of the test. But this should serve as a pretty good starting point.
To summarize:
This particular test should only really test the code within your extension method. Meaning, it should only ensure that you call CreateObjectSet<>(), get the list, and then call DeleteObject on each one.
It should not care at all if indeed the DeleteObject() altered the ObjectSet or not (in fact it won't, since it's a mock). That should be the responsibility of a test for the DeleteObject() method, but since I'm assuming that is actually an EF method, you should not write a test for third party components.

Categories

Resources