How to Mock ILogger / ILoggerService using Moq - c#

I'm writing some unit tests for my View Model class. The constructor of this class is injected with an ILoggerService. This interface defines 1 method GetLog which returns an ILogger. Something like below where this represents a class that implements ILoggable:-
protected ViewModelBase(ILoggerService loggerService)
{
Logger = loggerService.GetLog(this);
}
I'm trying to unit test my CreateNewOrder method that looks like below:
private void CreateNewOrder(INewOrderViewModel newOrderViewModel)
{
Logger.Log("Sending Create New Order Message", LogCategory.Info);
var createNewOrderMessage = new OrderMessage(newOrderViewModel);
_eventAggregator.GetEvent<CreateOrderEvent>().Publish(createNewOrderMessage);
}
How would I go about Mocking the ILoggerService so that a valid Logger is returned? At the moment my Unit test throws a NullReferenceExeception.
I'm using Moq to do my mocking.
I'm imagining I need to do something along the lines of
var loggerService = new Mock<ILoggerService>();
loggerService.Setup(svc => svc.GetLog(??))
But I can't see how without making my test class implement ILoggable.
Thanks in advance.

I'm not sure what the type is of the GetLog method parameter, but I assume it's something like object so the logger service can determine the type requesting a logger. You can use It to mock parameters in a method you are setting up, as seen below.
var logger = new Mock<ILogger>();
var loggerService = new Mock<ILoggerService>();
loggerService.Setup(c => c.GetLog(It.IsAny<object>())
.Returns(logger.Object);
Then pass logger.Object to whatever method or type needs an ILoggerService.

Related

.NET Core container definition for NUnit test project

I am quite new to .NET Core. How can I define a DI container within the NUnit class library project?
I know that it is done through IServiceCollection, but since there isn't any Startup method, I don't know where to get the instance implementing this interface.
Also I would like to be able to load definitions from other class libraries (being the subject of testing). That should be simpler as I can just create a static method in that class library with one parameter that is IServiceCollection, but again, how do I get it?
A side question is: I presume some of the interfaces could be mocked for the purpose of tests, but how can I replace a mapping already created using of of IServiceCollection's methods like AddSingleton or AddTransient?
There is a Remove method, but it is not documented.
IServiceCollection is implemented by the ServiceCollecion class. So if you want to do this for integration tests then you can use the ServiceCollection class to create your own ServiceProvider.
var services = new ServiceCollection();
services.AddTransient<IMyInterface, MyClass>();
services.AddScoped<IMyScopedInteface, MyScopedClass>();
...
var serviceProvider = sc.BuildServiceProvider();
You can now use the serviceProvider instance in your tests to get your classes:
var myClass = serviceProvider.GetService<IMyInterface>();
If you want to mock some of the interfaces instead of using the real ones then, instead of adding the real class/interface into the service collection you can add a mock instead:
mockInterface = new Mock<IMyInterface>();
sc.AddScoped<IMyInterface>(factory => mockInterface.Object);
Generally you don't want to create a DI container for your tests but, as you realise, you want to mock them instead. So, for example, if this is a class you want to test:
public class UserService
{
private readonly IUserDatabase _userDatabase;
public UserService(IUserDatabase userDatabase)
{
_userDatabase = userDatabase;
}
public bool DoesUserExist(int userId)
{
return _userDatabase.UserExists(userId);
}
}
And this is the definition of the interface used:
public interface IUserDatabase
{
bool UserExists(int userId);
}
In our tests we can mock the interface to return a specific value we want for our test:
[TestClass]
public class UserServiceTests
{
[TestMethod]
public void DoesUserExist_ForValidUserId_ReturnsTrue()
{
var fakeUserId = 123;
var mockUserDatabase = new Mock<IUserDatabase>();
mockUserDatabase.Setup(udb => udb.UserExists(fakeUserId)).Returns(true);
var userService = new UserService(mockUserDatabase.Object);
var result = userService.DoesUserExist(fakeUserId);
Assert.IsTrue(result);
mockUserDatabase.VerifyAll();
}
}
So in this test we have used Moq to create a mock of our interface. We don't need to use a DI container because we are in controller of creating the class we are testing. The DI container is of more use in production as it enables the application to create any dependencies it needs without your code having to call new - which is a big problem if you are trying to unit test your classes.
The .VerifyAll() method checks that any methods set up on the mock object, in this case we setup a call to UserExists, was actually called.
There are plenty of examples of how to use Moq and mocking interfaces in general. A quickstart guide to Moq is here.

Check if call to a method is made from another method using Moq

I am quite new to Moq and I am not sure is this even possible, but let say, if I have one method named GeneratedHashedAndSaltedPassword()and I am making a call to that method from method named CheckUsersPassword() is there any chance that i can write from Unit test Moq expression that says: Verify if GeneratedHashedAndSaltedPassword is call from CheckUsersPassword method?
I will know that CheckUsersPassword method preformed correctly if it makes a call to GeneratedHashedAndSaltedPassword method without any exception.
What I have for now is not much, since I am having difficult time with Moq and it's logic.
[Test]
public void CheckIfPasswordIsHashed_Test()
{
var securityServiceMock = new Mock<User>();
securityServiceMock.Setup(m => m.CheckUsersPassword(It.IsAny<string>())).Returns(true);
securityServiceMock.VerifyAll();
}
I was trying to SetUp CheckUsersPassword, but I still don't know how or even if I can preform Verification I need. Does somebody has more experience with this kind of issue?
This is what CheckUserPassword does:
public bool CheckUsersPassword(string password)
{
return SecurityService.GenerateHashedAndSaltedPassword(password, Salt) == Password;
}
It makes simple call to GenerateHashedAndSaltedPassword() and compares result with current user password.
Important is to distinguish between code which is tested with unit test and external dependencies of this code. External dependencies are mocked with MOQ but tested code must be instantiated and called in the unit test directly.
In your question I assume you test the method CheckUsersPassword and that SecurityService is a dependency which should be mocked.
In the test you have to create instance of class (which contains the tested method) and pass mock of dependency to this tested class somehow.
[Test]
public void CheckIfPasswordIsHashed_Test()
{
// Arrange
// Mock dependency which is the service and setup
// GenerateHashedAndSaltedPassword so it does what you need
var securityServiceMock = new Mock<User>();
securityServiceMock.Setup(m => m.GenerateHashedAndSaltedPassword(
It.IsAny<string>(),
ItIsAny<Salt>())
.Returns(Password);
// TestedClass needs a place where the mocked instance can be injected,
// e.g. in constructor, or public property
var testedClass = new TestedClass(securityServiceMock.Object);
// Act
testedClass.CheckUsersPassword(password);
// Assert
securityServiceMock.Verify(m => m.GenerateHashedAndSaltedPassword(
It.IsAny<string>(),
ItIsAny<Salt>()),
Times.Once());
}

Setup a Mocked (Moq) class that only exposes properties

I am trying to mock (using Moq) a class set a return object on a class that only exposes two properties.
In my limited Moq experience I would normally use a Setup() lamda to define the method call and then Returns() to spit back the desired output.
What I am falling down on here is the Setup(). There isn't a "method" to call as the constructor does the work, populates the two properties and then returns.
My class that I want to mock...obviously dummied down:
public class CarResponse
{
public IMetaModel meta { get; set; }
public List<ICarModel> cars { get; set; }
public CarResponse(Common.Models.Car car)
{
this.cars = new List<ICarModel>();
}
}
My feeble attempt at mocking:
private Mock<CarResponse> _carResponse = new Mock<CarResponse>(MockBehavior.Strict);
_carResponse.Setup( ????? ).Returns(new CarResponse() { meta = new MetaModelV2(), cars = foo });
To further clarify...here is the code I am trying to write a unit test for:
public HttpResponseMessage AddPickup()
{
//....code removed for brevity....
//this repository is mocked and returns the object exactly as I want it
var car = carRepository.GetCar(carId);
if (!errorInfo.Any()) //This check is bogus it never gets sets
{
RequestHelper rqh = new RequestHelper();
response = rqh.CreateResponse(Request, HttpStatusCode.OK, new CarResponse(car));
}
My unit test:
[TestMethod]
public void AddValidPickupCorrectResponse()
{
//arrange
//...lots of code here left off for setting up http context etc
//act---
var response = controller.AddPickup();
//assert
}
If I were to use a precanned object as suggested how would I "hook" it to the code under test. For example I write a unit test that uses my pre-canned object instead of a Moq but how do I get that pre-canned object to be used by the SUT?
There are few problems which can get in the way of properly unit testing the above code:
new-ing up the response helper
new-ing up the CarResponseObject
In essence, unless a class in real POCO (i.e. only data with public setters and getters), using "new" is a killer for unit testing. I.e. it is not a unit test (test the unit/method in isolation). It tests the behavior of the CarResponse ctor, as well as the working of RequestHelper.
Consider the following changes:
Inject the RequestHelper (so you can mock the CreateResponse method)
Use and inject some mapping factory of sort, which can create CarResponseObjects from Car.
Consider CarResponse to implement something like IResponse, so your RequestHelper, or factory, can return interfaces.
With all of the above, your test will look like (pseudo code, not complete):
//arrange
//....
var carInDB = new Car();
_repoMock.Setup(...).Returns(car);
var carResponse = Mock.Of<IResponse>();
_mapperMock.Setup(m=>m.CreateResponse(car).Returns(carResponse);
var responseFromHelper = new WhateverResponseIsNeeded(); //(or create a new mock IResponse - note! new mock, different than car response
_helperMock.Setup(_controller.Request, HttpStatusCode.OK, carResponse).Returns(responseFromHelper);
//act
var response = _controller.AddPickup();
//assert
response.Should().Be.SameInstanceAs(responseFromHelper)
You can use SetupGet and SetupSet to mock properties. However, I don't think you can mock concrete classes.
If you are dealing with a value type you might find it easier to not bother mocking and just used a pre-canned object.

AutoFixture as an Automocking container vs Automocking differences?

I started to use moq but from my understanding I always have to mock up all the methods that could be called even if I really do not care about them.
Sometimes it takes so long to mockup stuff you forget what you want to do. So I been looking at auto mocking but I am not sure what one I should use.
AutoFixture as an auto-mocking container
Automocking
I don't get how to use the first one at all. I sort of get the second one but never really tried it.
I am not sure if one is better than the other. The only thing I know is I am using AutoFixtures already what is a dependency of the first one.
So maybe in the long run it makes sense to go with the first one but like I said I can't find any basic tutorials on how to use it.
Edit
I am trying to follow "Nikos Baxevanis" examples but I am running into errors.
Failure: System.ArgumentException : A matching constructor for the given arguments was not found on the mocked type.
----> System.MissingMethodException : Constructor on type 'DatabaseProxyded46c36c8524889972231ef23659a72' not found.
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var fooMock = fixture.Freeze<Mock<IFoo>>();
// fooMock.Setup(x => x.GetAccounts(It.IsAny<IUnitOfWork>()));
var sut = fixture.CreateAnonymous<AdminService>();
sut.Apply();
fooMock.VerifyAll();
I think it is because of my petapoco unitOfWork property
PetaPoco.Database Db { get; }
Not sure if I got to mock this up somehow or what.
While I have never used moq-contrib Automocking, I could probably provide some information on using AutoFixture as an auto-mocking container.
Currently there is support for Moq, Rhino Mocks, FakeItEasy, and NSubstitute. Just install the appropriate extension AutoMoq, AutoRhinoMocks, AutoFakeItEasy, and AutoNSubstitute.
Once you have installed one of the extensions for Auto Mocking the extra call is:
var fixture = new Fixture()
.Customize(new AutoMoqCustomization());
(or if you are using Rhino Mocks)
var fixture = new Fixture()
.Customize(new AutoRhinoMockCustomization());
(or if you are using FakeItEasy)
var fixture = new Fixture()
.Customize(new AutoFakeItEasyCustomization());
(or if you are using NSubstitute)
var fixture = new Fixture()
.Customize(new AutoNSubstituteCustomization());
Example 1
public class MyController : IController
{
public MyController(IFoo foo)
{
}
}
public interface IFoo
{
}
Here is how to use AutoFixture to create instances of MyController class:
var fixture = new Fixture()
.Customize(new AutoMoqCustomization());
var sut = fixture.CreateAnonymous<MyController>();
Now, if you inspect the sut variable you will see the the IFoo is a mocked instance (having a type name similar to Castle.Proxies.IFooProxy).
Example 2
This examples extends the previous one.
You can instruct AutoFixture to use your own, pre-configured, mocked instance:
var fooMock = fixture.Freeze<Mock<IFoo>>();
// At this point you may setup expectation(s) on the fooMock.
var sut = fixture.CreateAnonymous<MyController>();
// This instance now uses the already created fooMock.
// Verify any expectation(s).
That's basically it - but it can go further!
Below are the previous examples using AutoFixture decleratively with the xUnit.net extension.
Example 1
[Theory, AutoMoqData]
public void TestMethod(MyController sut)
{
// Start using the sut instance directly.
}
Example 2
[Theory, AutoMoqData]
public void TestMethod([Frozen]Mock<IFoo> fooMock, MyController sut)
{
// At this point you may setup expectation(s) on the fooMock.
// The sut instance now uses the already created fooMock.
// Verify any expectation(s).
}
You may find more information on this blog post which contains links to everything related around AutoFixture, xUnit.net, and Auto Mocking.
Hope that helps.

Problem with matching setup in Moq

I've been using Moq for the past week or so and haven't had any issues until today. I'm having a problem with getting VerifyAll() to properly match the setup of my mock.
I'm currently writing unit tests for my application's API. Here's how the application is structured:
API <==> Service <==> DAO <==> Database
With this in mind, I'm mocking the service object and then constructing an API object using the mocked service. I've written a number of unit tests already without problem up until now.
I have two instance variables like this:
private Api _api;
private Mock<IHibernateService> mockService;
I initialize these in a setup method:
[SetUp]
public void DoSetupTasks()
{
mockService = new Mock<IHibernateService>();
_api = new Api(mockService.Object);
}
Here is the unit test that is failing:
[Test]
public void TestSearchOnAllProperties()
{
mockService
.Setup(service => service.LoadAll(It.IsAny<Type>()))
.Returns(new DomainBase[0]);
var dmbs = _api.SearchOnAllProperties("search term", typeof(DomainBase));
mockService.VerifyAll();
}
The API's SearchOnAllProperties() method will subsequently make a call to the service's LoadAll() method (with some additional logic of course), so I want to verify that it's being called properly. To clarify, here's how LoadAll() is being called in SearchOnAllProperties():
public IEnumerable<DomainBase> SearchOnAllProperties(string searchTerm, Type type)
{
foreach (DomainBase dmb in _hibernateService.LoadAll(type))
{
// additional logic
}
}
However, when I run the unit test, I get a MockVerificationException stating that the given setup was not matched. I cannot figure out why as it should be calling the service's LoadAll() method.
One possible cause is that at some point before this particular test method is called, mockService is being assigned to a new instance of Mock<IHibernateService>. If that is the case, then this test method would be calling Setup on the wrong instance, which would then produce this exception.
A quick way to test this would be to use local mockService and api variables and see if the test still fails:
[Test]
public void TestSearchOnAllProperties()
{
var localMockService = new Mock<IHibernateService>();
var localApi = new Api(localMockService.Object);
localMockService
.Setup(service => service.LoadAll(It.IsAny<Type>()))
.Returns(new DomainBase[0]);
var dmbs = localApi.SearchOnAllProperties("search term", typeof(DomainBase));
localMockService.VerifyAll();
}
HTH

Categories

Resources