Unit test for methods with disposable - c#

I have a problem with unit testing.
I have a standart Reprository and UnitOfWork pattern.
For example, I have a UnitOfWork class:
public class UnitOfWork : IDisposable
{
private readonly MyDbContext _context;
... repositories
private IMyEntityRepository _myEntityRepository;
...
}
UnitOfWok used in another part of program witch make some special operations with entities. For example, there is a method, whitch use UnitOfWork:
public IEnumerable<MyClass> MyMethod()
{
using (_unitOfWork = new UnitOfWork())
{
var myEntities= _unitOfWork.MyEntityRepository.Get();
var result = ... some logic to convert myEntities collection to IEnumerable<MyClass>
return result;
}
}
My question is how to write unit tests for MyMethod if there is consruction using(_unitOfWork = new UnitOfWork)? How could I use fake UnitOfWork with Fake context in that case? Thanks for any advice.

To make your classes more fake-able and testable I would suggest abstracting your UnitOfWork and Repositories if possible and then use a factory to inject them into the classes that depend on them.
public interface IUnitOfWork : IDisposable {
... repositories
IMyEntityRepository MyEntityRepository;
...
}
And your UnitOfWork will derive from that interface
public class UnitOfWork : IUnitOfWork {...}
IUnitOfWorkFactory
public interface IUnitOfWorkFactory {
IUnitOfWork Create();
}
With that, a dependent class can then look like this
public class MyDependentClass {
private readonly IUnitOfWorkFactory unitOfWorkFactory;
public MyDependentClass (IUnitOfWorkFactory unitOfWorkFactory) {
this.unitOfWorkFactory = unitOfWorkFactory;
}
public IEnumerable<MyClass> MyMethod() {
using (var _unitOfWork = unitOfWorkFactory.Create()) {
var myEntities= _unitOfWork.MyEntityRepository.Get();
var result = ... some logic to convert myEntities collection to IEnumerable<MyClass>
return result;
}
}
}
Now you can mock/fake your UnitOfWork and Repositories with no need to fake the Context.
Lets say you want to test/verify that the UOW is actually disposed of after calling MyMethod
(I'm using Moq and FluentAssert for demonstrative purposes)
You can construct a test as follows:
[TestMethod]
public void UOW_Should_Be_Disposed() {
//Assert
var fake_entities = Enumerable.Range(1, 10).Select(i => new MyEntity());
var mockRepository = new Mock<IMyEntityRepository>();
mockRepository.Setup(m => m.Get()).Returns(fake_entities);
var mockUOW = new Mock<IUnitOfWork>();
mockUOW.Setup(m => m.MyEntityRepository).Returns(mockRepository.Object);
var mockFactory = new Mock<IUnitOfWorkFactory>();
mockFactory.Setup(m => m.Create()).Returns(mockUOW.Object);
//Act
var sut = new MyDependentClass(mockFactory.Object);
var output = sut.MyMethod().ToList();
//Assert
output.Should().NotBeNull();
output.Should().HaveCount(10);
output.Should().ContainItemsAssignableTo<MyClass>();
mockUOW.Verify(m => m.Dispose());
}
The above shows how you can test everything easily using the frameworks mentioned.
Hope this helps

You have to inject a factory of UnitOfWork into the class that contains the MyMethod method via constructor injection like this:
public class MyClass
{
private readonly Func<UnitOfWork> unitOfWorkFactory;
public MyClass(Func<UnitOfWork> unitOfWorkFactory)
{
this.unitOfWorkFactory = unitOfWorkFactory;
}
public IEnumerable<MyClass> MyMethod()
{
using (unitOfWork = unitOfWorkFactory())
{
//..
}
}
}
Please note that the class takes a Func<UnitOfWork> instead of a UnitOfWork because I am assuming that you want each call to MyMethod to have a new instance of UnitOfWork.
In your tests, you create a fake UnitOfWork and then you can pass it to the MyClass instance like this:
var sut = new MyClass(() => fakeInstance);
You also need to make sure that UnitOfWork is fakeable. For example, since it is a concrete class, you need to make sure that the relevant methods are virtual. Another approach is to have an interface IUnitOfWork that UnitOfWork implements and that MyClass uses.

Related

Instantiate another class in sealed class

What is the recommended way to instantiate another class inside a sealed class:
public sealed class AvayaService
{
private static Lazy<AvayaService> lazy =
new Lazy<AvayaService>(() => new AvayaService());
public static AvayaService AvayaServiceInstance
{
get
{
if (!lazy.IsValueCreated)
lazy = new Lazy<AvayaService>(() => new AvayaService());
return lazy.Value;
}
}
private AvayaService()
{
}
public static Response GetResponse(Request request)
{
var _repository = new Repository(); // what is the best way to get the instance here
}
}
public class Repository : IRepository
{
...
}
I am trying to learn sealed class and lazy instantiation however I am pondering over what should be the recommended way to instantiate another class in a sealed class?
There's no "recommendations" in this area. If you've read recommendations, read again, most probably it was just an exercise. It gives you an idea, but using this idea in a real project is up to you. Sometimes those exercises demonstrate an opposite approaches. Sometimes the repository owner will dictate the style which is against of any rules you've read before, and it's totally fine.
Here's another instantiation exercise which I think is helpful to try: to never instantiate anything except value objects. Delegate instantiation to a container. Avoid singleton pattern, but register your service as a singleton in your container. In this way your code will look like:
public sealed class AvayaService
{
private readonly IRepository _repository;
public AvayaService(IRepository repository)
{
if(repository == null)
throw new ArgumentNullException();
_repository = repository;
}
public static Response GetResponse(Request request)
{
// use _repository
}
}

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.

How to assign a mocked object to a object in controller?

I have a controller which contains a business class that internally has dependencies to a datahandler. For testing that business class I need to mock the datahandler. After setup, I am assigning the business class' datahandler with the mocked datahandler. But while debugging, the business class' datahandler is showing null , I know that I should use the constructor to inject the mocked object.But is it possible to do it without using any constructor injection ?Can any body help me with this?
my business class:
public class FooBusiness
{
public static BarDataHandler _barDatahandler = new BarDataHandler();
...
}
Test class:
public class FooBusinessTest
{
...
_mockedBarDataHandler = new Mock<IBarDataHandler>(){CallBase:true};
public FooTestMeth()
{
//Arrange
_mockedBarDataHandler.Setup(x=>x.Search(It.IsAny<int>).Returns(1);
...
FooBusiness _fooBusiness = new FooBusiness();
FooBusiness._barDatahandler = _mockedBarDataHandler.Object;
//Act
...
}
}
As I mentioned, there are multiple ways to achieve your needs.
Personally I like Shyju's answer more (Constructor Injection), but if you can't change the constructor, you can still change the implementation afterwards by setting the property:
business class:
public class FooBusiness
{
private IBarDataHandler _barDatahandler = new BarDatahandler();
public IBarDataHandler BarDatahandler
{
get { return _barDatahandler; }
set { _barDatahandler = value; }
}
public int Search(int a)
{
return _barDatahandler.Search(a);
}
}
Test class:
public class FooBusinessTest
{
_mockedBarDataHandler = new Mock<IBarDataHandler>(){CallBase:true};
public FooTestMeth()
{
//Arrange
_mockedBarDataHandler.Setup(x => x.Search(It.IsAny<int>).Returns(1);
FooBusiness fooBusiness = new FooBusiness();
fooBusiness.BarDatahandler = _mockedBarDataHandler.Object;
//Act
}
}
If you worry about to refactor the implementation, it is better to setup all the tests first. After that you can refactor with a safer feeling :)
You need to inject your dataHandler dependency to FooBusiness
You need to extract an interface for your BarDataHandler if one does not exist.
interface IBarDataHandler
{
string GetUserToken(int id);
}
public class BarDataHandler : IBarDataHandler
{
public string GetUserToken(int id)
{
// to do :read from db and return
}
}
And add a constructor to FooBusiness class which accepts an implementation of IBarDataHandler.
public class FooBusiness
{
IBarDataHandler barDataHandler;
public FooBusiness(IBarDataHandler barDataHandler)
{
this.barDataHandler=barDataHandler
}
public string GetUserToken(int id)
{
return this.barDataHandler.GetUserToken(id);
}
}
You can use any one of the dependency injection frameworks like Unity/Ninject/StructureMap to resolve your concrete implementation when your app runs.
You can use any mocking framework like Moq to mock the fake implementation of IBarDataHandler in your unittests.

Class which supports injectable mocked object but also using statement c#

How do I go about creating a class which wraps all EF repository calls in a Using statement whilst also supporting an injectable interface of the repository?
I can't seem to wrap my head around having this class support 2 different types of instantiation.
public class MyClass(IRepo repo)
{
_repo = repo;
}
public void MyMethod()
{
using ( var db = new DbContxt() )
{
var repo = new Repo(db);
repo.GetById(1);
}
}
In essence, the life-time of the 'db' object is the lifetime of the method call. Whereas the lifetime of 'db' would be managed outside of the class if injected.
You could structure it this way:
public class MyClass
{
private readonly IRepo _repo;
//or if you want a parameterless constructor...
public MyClass() : this(new Repo()) { }
public MyClass(IRepo repo)
{
_repo = repo;
}
public MyObject MyMethod(int id)
{
_repo.GetById(id);
}
}
public interface IRepo
{
MyObject GetById(int id);
}
public class Repo : IRepo
{
public MyObject GetById(int id)
{
using ( var db = new DbContext())
{
//do your db related stuff here
}
}
}
You would need a way of injecting an instance of Repo into MyClass so maybe take a look at IoC.
This way, you can easily mock IRepo for testing purposes.
You shouldn't do it that way. Have a parameterless constructor for your Repo, and instantiate the DbContext there. You can also have an overload for it that takes a DbContext, but you don't have to go about it that way. The point is to let each layer only worry about what it needs on its own. Let the IOC container inject everything as it is created, don't make objects for a different layer inside your methods.

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