How much do moq mock objects resemble the actual classes? - c#

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.

Related

Mocking a method that takes a mocked parameter object in C#

The to be tested method
public string GetPopulatedField(string input)
{
IParameterCollection sqlParams = CreateParameterCollection();
sqlParams.Add("param", input);
string recordCollection = DataAccess.ExecuteSelect(SQL, ref sqlParams);
return recordCollection ;
}
The test method
public void Test()
{
// Mocking one of the dependencies used by the ExecuteSelect
MockHelper.CreateAndRegisterMock<IParameterCollection>();
Mock<Access> mock = new Mock<Access>();
//mocking the ExecuteSelect Method that takes a string and and IParameterCollection
mock.Setup(t => t.ExecuteSelect(It.IsAny<string>(),ref It.Ref<IParameterCollection>.IsAny)).Returns("123");
//The execute Select is called from the GetPopulatedField method
var x= MockHelper.CreateAndRegisterMock<PopulateField>("Container");
Assert.AreEqual("123", x.Object.GetPopulatedField("value"));
}
The issue is when ExecuteSelect is called from GetPopulateField it is using the Mock object and not the actual IParameterCollection, so what is the correct way to Mock the ExecuteSelect properly?
ref It.Ref<IParameterCollection>.IsAny I believe this should be changed to reflect the mocked one.
In a unit test, it is important to only test a unit, a small portion of code. The smaller the unit,
the easier the reason can be found if a failure occurs.
the faster the tests can be run.
In order to reduce the code to the relevant unit, two aspects are important:
you want to test the real code of the unit as it would be used in the program flow - hence you create a real instance of the class you want to test, not a mock.
you do not want to test code that the unit depends on - therefore
you structure your code in a way that you can replace dependencies with mocks and
you create mocks for the dependencies when testing.
With that in mind, you could change your PopulateField class like this:
public class PopulateField
{
private readonly IDataAccess _dataAccess;
public PopulateField(IDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
public string GetPopulatedField(string input)
{
IParameterCollection sqlParams = CreateParameterCollection();
sqlParams.Add("param", input);
string recordCollection = _dataAccess.ExecuteSelect(SQL, ref sqlParams);
return recordCollection;
}
// ...
}
With an instance of type IDataAccess injected into the constructor and used in the GetPopulatedFields method, you can easily replace it with a mock in the tests:
public void Test()
{
// Create a mock for the data access
Mock<IDataAccess> mockDataAccess = new Mock<IDataAccess>();
//mocking the ExecuteSelect Method that takes a string and and IParameterCollection
mockDataAccess.Setup(t => t.ExecuteSelect(It.IsAny<string>(),ref It.Ref<IParameterCollection>.IsAny())).Returns("123");
// Create an instance of PopulateFields so the tests run on real code
var pf = new PopulateFields(mockDataAccess.Object);
var actual = pf.GetPopulatedFields("input");
Assert.AreEqual("123", actual);
}
Please note that the creation of the IParameterCollection happens in a method of PopulateFields that you cannot replace with this behavior. There are two ways to go about this:
If it is important to also mock the instantiation of the ParameterCollection, you need to create a factory interface that contains a method that returns the IParameterCollection instance. Along with IDataAccess an instance implementing this interface is also injected into the constructor of PopulateFields so you can replace it with a mock when testing.
If you only want to validate that the correct parameters are set when GetPopulatedFields is called, you can add a validation to the setup. Unfortunately, for It.Ref<T> there is only a IsAny and no Is method that allows deciding whether the parameters match, so we solve it with a callback:
mock.Setup(t => t.ExecuteSelect(It.IsAny<string>(),ref It.Ref<IParameterCollection>.IsAny)).Callback((string s, ref IParameterCollection params) => {
if (!params.Contains("param")) // Adjust conditions to IParameterCollection
throw new ApplicationException("Parameter was not added");
}.Returns("123");

How to unit test a method or constructor which creates a new instance of another class

I've done extensive research on this topic and have yet to find a reliable answer so here goes.
I have a constructor I'd like to test. This constructor initializes another class in order to set a global variable which is necessary throughout the rest of the class. However, the constructor of the class which the constructor initializes has dependencies on things like web session and other variables being set which are not set when the any tests run. How can I properly mock this to make sure I'm just testing the constructor?
Here's the constructor to be tested:
public CheckoutManager()
{
_orderController = new OrderController();
_orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}
The problem lies in the OrderController constructor:
public OrderController()
{
_customer = WebUserSession.Current.Profile.Customer;
_srd = ContextManager.GetStandardRequestByCulture( CultureInfo.CurrentUICulture.Name );
WarehouseData data = new WarehouseData();
data.WarehouseID = 0; // TODO: Convert the 0 warehouse to a web warehouse type
// Grab the attention items from the session
AttentionItems = WebUserSession.Current.OrderAttentionItems;
// Load the shopping cart
_cart = ShoppingCartManager.Cart;
}
Here is my attempted test:
[TestMethod]
public void Constructor_ExpectInstantiation()
{
var checkoutManager = new CheckoutManager();
Assert.IsNotNull( checkoutManager );
}
It bombs out at the _customer = WebUserSession.Current.Profile.Customer; line. How do you mock this using Moq? If it cannot be mocked, is there a good explanation as to why? How could the original constructor be modified to have the same functionality in a more testable way? Thank you in advance.
You can use Dependency Injection, which is a form of Inversion of Control, to solve these kind of problems.
Instead of instantiating your OrderController in the constructor, pass it as an argument:
public CheckoutManager(OrderController orderController)
{
_orderController = orderController;
_orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}
You can then either instantiate the OrderController either manually somewhere in a Main-like method, or with a library like Autofac which will do all the wiring for you.
So now you can mock your interface in your test:
[TestMethod]
public void Constructor_ExpectInstantiation()
{
Mock<OrderController> mockOrderController = new Mock<OrderControler>();
var checkoutManager = new CheckoutManager(mockOrderController.Object);
Assert.IsNotNull( checkoutManager );
}
That way, the constructor of OrderController will never be called (it's a mock) and it won't interfere with your tests of CheckoutManager. If you need to test some interactions with it, you can Setup and Verify specific methods using Moq.
You won't be able to use Moq test to this code. You could
Modify the code to make it more testable by adding a constructor that accepts an OrderController
Use a more "advanced" testing technique such as shims.

Moq fake one method but use real implementation of another

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.

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.

RhinoMocks AssertWasCalled on mocked object's method that needs to have an object returned?

Using RhinoMocks, I have a catch-22 situation: I want to verify that a method is called, but this method needs to have an object returned on it because the returned object is acted on in the next line. In other words, mocking on the interface just returns a null value, but not mocking it up doesn't give me any way to verify that the method was called apart from some kind of integration test.
Therefore, looking at the contrived sample below that I threw together, is there a way to do what I'm wanting? I thought there might be a way to set the AssertWasCalled method to actually return something as when stubbing a method, but...thanks for any pointers (especially if it's simply a design flaw that should be addressed instead).
public class SomeClass
{
private readonly ISomeMapper _someMapper;
[Inject]
public Test(ISomeMapper someMapper)
{
_someMapper = someMapper;
}
public SomeReturnType SomeMethod(IEnumerable<ISomethingToMap> somethings)
{
//foreach over somethings and do something based on various properties for each
MappedSomething mappedSomething = _someMapper.Map(something); // AssertWasCalled here
mappedSomething.SomeProperty = somethingFromSomewhere; // Which gets a null reference exception here (understandably) if _someMapper is mocked
//end foreach after more stuff
}
}
///...
[Test]
public void the_mapper_should_be_called()
{
//If mock or stub, then can AssertWasCalled, but then only null object returned.
// If don't mock, then cannot assert whether was called.
var mapper = MockRepository.GenerateStub<ISomeMapper>();
var somethingToMap = _someListOfSomethings[0];
var sut = new SomeClass(mapper);
sut.SomeMethod(_someListOfSomethings);
mapper.AssertWasCalled(x => x.Map(somethingToMap));
}
You can set an expectation on the mock object that the method was called along with the return value:
MappedSomething fakeMappedSomething = //whatever
mapper.Expect(m => m.Map(something)).Return(fakeMappedSomething);
...
sut.SomeMethod(_someListOfSomethings);
Then verify the expectations at the end of the test.

Categories

Resources