FakeItEasy: how to unit test abstract class - c#

I want to mock abstract class public method to returns different values. Is it doable using fakeiteasy?
public class Worker: IInterface
{
private readonly ILogger _logger;
provate readonly IServiceProvider _serviceProvider;
public Worker(ILogger logger, IServiceProvider provider)
{
_logger = logger;
_serviceProvider = provider;
}
public Handler(Order order)
{
var service = _serviceProvier.GetService(order.Properties.Type);
service.DoTaskAsync(...);
}
}
public abstract class ServiceBases
{
public async Task DoTaskAsync(...);
}
[Fact]
public async Task WorkerHandler_Return_Success()
{
// how to mock ServiceBases.DoTaskAsync to returns null or throw exception ?
}

This is complicated because you've got two things to figure out:
How to create a mock of your abstract class
How to set up your IServiceProvider to return an instance of the class that inherits from the abstract class.
Let's start with mocking the abstract class. The easiest way to do that is to create a class that implements the abstract class. You could do this:
public class FakeServiceBases : ServiceBases
{
public int NumberOfTimesCalled { get; private set; }
public override async Task DoTaskAsync()
{
NumberOfTimesCalled++;
}
}
Presumable you're mocking this so that you can make sure the class that depends on this calls DoTaskAsync(). If you create an instance of this fake class then when Handler calls it, it will increment the value. When the test runs you can check that the value has been incremented.
Or maybe you want to make sure that the expected arguments were passed. I don't know what the arguments are, but when DoTaskAsync() is called you can add the arguments to a list instead of incrementing a number, like this:
public class FakeServiceBases : ServiceBases
{
public List<SomeArgumentType> CallsToDoAsync { get; } = new List<SomeArgumentType>();
public override async Task DoTaskAsync(SomeArgumentType someArgument)
{
CallsToDoAsync.Add(someArgument);
}
}
Same thing. After calling your Handler method you can inspect the arguments that were passed to service.DoTaskAsync by looking at what's in the CallsToDoAsync list.
That takes care of mocking ServiceBases. The other step is getting your IServiceProvider to always return a FakeServiceBase regardless of the type passed to it.
That you can do with FakeItEasy.
var fakeServiceBase = new FakeServiceBases();
var serviceProvider = A.Fake<IServiceProvider>();
A.CallTo(() => serviceProvider.GetService(A<Type>.Ignored)).Returns(fakeServiceBase);
var testSubject = new Worker(NullLogger.Instance, serviceProvider);
This creates a faked IServiceProvider. Whenever GetService is called, regardless of the type passed to it, it will return the instance of FakeServiceBases that you created. After calling methods on the Worker you can inspect fakeServiceBase to make sure methods were called on it like you expected.
We can make this class easier to test by removing the dependency on IServiceProvider.
Let's change Worker to look like this:
public class Worker
{
private readonly ILogger _logger;
private readonly Func<Type, ServiceBases> _getServicesBases;
public Worker(ILogger logger, Func<Type, ServiceBases> getServicesBases)
{
_logger = logger;
_getServicesBases = getServicesBases;
}
public async Task Handler(Order order)
{
// Calls the function - passes a Type and gets a ServiceBases
var service = _getServicesBases(order.Properties.Type);
service.DoTaskAsync(...);
}
}
Now it doesn't depend on IServiceProvider. It depends on a Func<Type, ServiceBases>. In other words, it depends on a function that will take a Type and return an object that implements ServicesBases.
When you're registering your types in your Startup you can do this:
services.AddSingleton<Func<Type, ServiceBases>>(serviceProvider =>
new Func<Type, ServiceBases>(type => (ServiceBases)serviceProvider.GetService(type)));
So at runtime the function will actually resolve the type from the IServiceProvider.
But now that your class depends on a function, the mock is even simpler. You don't need to mock an IServiceProvider. Instead, you provide a "real" function that returns your FakeServiceBases:
var fakeServiceBase = new FakeServiceBases();
Func<Type, ServiceBases> getServiceBases = type => fakeServiceBase;
var testSubject = new Worker(NullLogger.Instance, getServiceBases);

Related

AutoFixture AutoMoq partially covers class constructor

I am using AutoFixture AutoMoq and it's greatly simplifies the mock for all interface used in class and initialize it.
Though I noticed the constructor code is partially covered, can we modify AutoMoqDataAttribute so that constructor ArgumentNullException can also be covered?
public class ServiceTest
{
[Theory, AutoMoqData]
public async Task Do_Test_For_DoMethod(Service sut)
{
await sut.DoMethod();
}
}
AutoMoqData attribute class,
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(() => new Fixture().Customize(new AutoMoqCustomization()))
{
}
}
Service class code,
public class Service
{
private readonly IServiceClient _serviceClient;
private readonly ILogger<Service> _logger;
public Service(IServiceClient serviceClient, ILogger<Service> logger)
{
_serviceClient = serviceClient ?? throw new ArgumentNullException(nameof(serviceClient));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task DoMethod()
{
await _serviceClient.Do();
}
}
It is not the responsibility of the AutoDataAttribute to know how to cover your code. It is the developers responsibility to express intent and explicitly cover the scenario.
In your case the uncovered branches are the null guards. Luckily AutoFixture provides a library just for that, AutoFixture.Idioms.
This library provides idiomatic assertions, that encapsulate most basic test scenarios like null guards, property setters, equality members and so on.
Using this library you can write a test like the following.
[Theory, AutoMockData]
void CheckGuards(GuardClauseAssertion assertion)
{
assertion.Verify(typeof(Service));
}
This should cover all the parameters of all the constructors, and the nice part is that it uses your customization, so it will generate valid data when attempting to instantiate your object.

Creating an instance of generic class, how to easily set the type to the calling class

I have a generic class LoggerHelper<T>. There are properties in many different classes in the application, whose values are to be set to instances of LoggerHelper. In the constructors of these classes, this property will be set. For example:
public class Importer
{
ILogger _logger;
public Importer()
{
this._logger = new LoggerHelper<Importer>();
}
}
How can I avoid specifying the type each time? Is there are suitable pattern for this?
You could use a factory method, thus a type could be inferred by the compiler.
Static method
public static class LoggerHelperFactory
{
public static LoggerHelper<T> Create<T>(T instance)
{
return new LoggerHelper<T>();
}
}
Then you can call it as:
_logger = LoggerHelperFactory.Create(this);
Extension method
public static class LoggerHelperFactoryExtensions
{
public static LoggerHelper<T> CreateLogger<T>(this T instance)
{
return new LoggerHelper<T>();
}
}
Usage:
_logger = this.CreateLogger();

When using Moq, are mocked interfaces implemented methods supposed to execute?

I am new to using Moq and have not unit tested in about 5 years. Many things have changed.
I'm trying to wrap my head around the basics.
I have an interface.
public interface ILogger
{
void Log(string message)
}
And this interface is implemented in the following way.
public class MyLogger : ILogger
{
public virtual void Log(string message)
{
StaticClass.StaticMethodNotToBeCalled<ILogger>().Log(message);
}
}
I am testing the following logic.
public class MyClass
{
public MyMethod(int z)
{
var logger = new MyLogger();
if(z == 5)
{
logger.Log("it is true");
return true;
}
logger.Log("it is false);
return false;
}
}
My test looks like the following.
[TestMethod]
public void Test_MyMethod()
{
var mock = new Mock<ILogger>();
mock.Setup(y => y.Log(It.IsAny<string>()).Verifiable();
var o = new MyClass();
var result = o.MyMethod(5);
Assert.IsTrue(result);
mock.Verify();
}
The issue I am running into is the static method being called in the implementation of the ILogger interface.
I am guessing I just do not have a good understanding on what exactly a mock should.
What I would like to do is that any time ILogger.Log it is overridden and does not call that static method.
Is this possible?
Am I going about this a wrong way?
You're creating a Mock based on the ILogger interface, but you are not injecting the Mock into your MyClass instance. When MyClass executes it uses an instance of Logger instead of your ILogger mock.
Consider something like this for your class instead:
public class MyClass
{
private ILogger logger;
public MyClass(ILogger loggerInstance)
{
logger=loggerInstance;
}
public MyMethod(int z)
{
if(z == 5)
{
logger.Log("it is true");
return true;
}
logger.Log("it is false);
return false;
}
}
Note that in the constructor of MyClass you are now accepting an instance of a class that implements the ILogger interface. This allows you to inject your mock object in place of the actual concrete Logger:
[TestMethod]
public void Test_MyMethod()
{
var mock = new Mock<ILogger>();
mock.Setup(y => y.Log(It.IsAny<string>()).Verifiable();
var o = new MyClass(mock.Object);
var result = o.MyMethod(5);
Assert.IsTrue(result);
mock.Verify();
}
Dependency injection is the concept that you're missing in your scenario. It is imperative in many cases to writing unit-testable code.

Inject object using MEF with information about destination object

I am looking for a way to inject a logging object which wraps a log4net logger into various objects using MEF. The problem I currently have is that the logging object requires the type of the object it is a member of. I could get round this problem by setting the type property on the logging object within the constructor of the containing object, however this leaves the onus of setting the type on the developer, and there is no compile time restriction I can think of to enforce this.
I there a way to specify that when the logging object is generated by MEF and injected, its constructor parameter is set to the type of the target class of the injection?
My logger implements an interface
public interface ILogger
{
Type Type { get; }
}
An Example of the concrete implementation of this is
[Export(typeof(Ilogger))]
public class SimpleLogger : ILogger
{
public SimpleLogger(Type typeOfObjectToLogFor)
{
this.Type = typeOfObjectToLogFor
}
public Type Type { get; }
public void Info(string message)
{
//log the messsage including the type information
}
}
and it is currently consumed not using MEF as:
public class ExampleObject
{
private readonly ILogger logger = new SimpleLogger(typeof(ExampleObject));
public ExampleObject(){}
public void MethodThatLogs()
{
logger.Info("MethodThatLogs called");
}
}
and what I would like to do is inject it using constructor injection:
public class ExampleObject
{
private readonly ILogger logger;
[ImportingConstructor]
public ExampleObject(Ilogger injectedLogger)
{
logger = injectedLogger;
}
public void MethodThatLogs()
{
logger?.Info("MethodThatLogs called");
}
}
I could do all this with lazy evaluated reflection, but it feels like something that should be possible from a decent DI container, and hopefully that means that MEF will support it, cam anyone help?
By default, specifying an [Export] attribute, you're setting the PartCreationPolicy to Shared, which means that the container will create a singleton for your export - your logger.
But I suggest you to export not a class but a factory method that will accept one argument and create the logger for you.
class LoggerFactory
{
[Export("GetLogger")]
public ILogger GetLogger(Type type)
{
return new SimpleLogger(type);
}
}
class ExampleObject
{
private readonly ILogger logger;
[ImportingConstructor]
public ExampleObject([Import(ContractName = "GetLogger", AllowDefault = true)]Func<Type, ILogger> loggerCreator)
{
logger = loggerCreator?.Invoke(this.GetType());
}
}

moq only one method in a class

I'm using moq.dll
When I mock a class(all the IRepository interface) i use this line code
int state = 5;
var rep = new Mock<IRepository>();
rep.Setup(x => x.SaveState(state)).Returns(true);
IRepository repository = rep.Object;
but in this case i mock all the function in repository class.
Then all the methods in class repository are substituted with the methods setup of Mock dll
I want use all the methods defined in class repository(the real class) and mock only one function(SaveState)
How can I do this? Is possible?
You can create an instance of the real repository, then use the As<>() to obtain the desired interface, which you can then override with the setup, like this:
var mockRep = new Mock<RealRepository>(ctorArg1, ctorArg2, ...)
.As<IRepository>();
mockRep.Setup(x => x.SaveState(state)).Returns(true);
Then mockRep.Object as the repository dependency to the class under test.
Note that you will only be able to Mock methods on the Interface*, or virtual methods, in this way.
Update : *This might not work in all scenarios, since .Setup will only work on virtual methods, and C# interface implementations are "virtual" and sealed by default. And using As() will prevent the partial mock behaviour.
So it appears that the RealRepository concrete class will need to implement the IRepository interface with virtual methods in order for the partial mock to succeed, in which case CallBase can be used for the wire-up.
public interface IRepo
{
string Foo();
string Bar();
}
public class RealRepo : IRepo
{
public RealRepo(string p1, string p2) {Console.WriteLine("CTOR : {0} {1}", p1, p2); }
// ** These need to be virtual in order for the partial mock Setups
public virtual string Foo() { return "RealFoo"; }
public virtual string Bar() {return "RealBar"; }
}
public class Sut
{
private readonly IRepo _repo;
public Sut(IRepo repo) { _repo = repo; }
public void DoFooBar()
{
Console.WriteLine(_repo.Foo());
Console.WriteLine(_repo.Bar());
}
}
[TestFixture]
public class SomeFixture
{
[Test]
public void SomeTest()
{
var mockRepo = new Mock<RealRepo>("1st Param", "2nd Param");
// For the partially mocked methods
mockRepo.Setup(mr => mr.Foo())
.Returns("MockedFoo");
// To wireup the concrete class.
mockRepo.CallBase = true;
var sut = new Sut(mockRepo.Object);
sut.DoFooBar();
}
}
I came to this page because I had exactly the same problem: I needed to mock a single method, which was relying on many external sources and could produce one of three outputs, while letting the rest of the class do its work. Unfortunately the partial mock approach proposed above did not work. I really don't know why it did not work. However, the main problem is that you can't debug inside such mocked class even if you put break points where you want. This is not good because you might really need to debug something.
So, I used a much simpler solution: Declare all methods that you want to mock as virtual. Then inherit from that class and write one-liner mock overrides to return what you want, for example:
public class Repository
{
/// <summary>
/// Let's say that SaveState can return true / false OR throw some exception.
/// </summary>
public virtual bool SaveState(int state)
{
// Do some complicated stuff that you don't care about but want to mock.
var result = false;
return result;
}
public void DoSomething()
{
// Do something useful here and assign a state.
var state = 0;
var result = SaveState(state);
// Do something useful with the result here.
}
}
public class MockedRepositoryWithReturnFalse : Repository
{
public override bool SaveState(int state) => false;
}
public class MockedRepositoryWithReturnTrue : Repository
{
public override bool SaveState(int state) => true;
}
public class MockedRepositoryWithThrow : Repository
{
public override bool SaveState(int state) =>
throw new InvalidOperationException("Some invalid operation...");
}
That's all. You can then use your mocked repos during unit tests AND you can debug anything you need. You can even leave the protection level below public so that not to expose what you don't want to expose.

Categories