I have added a unit test to a mvc5 application manually.
This is my business logic
public void AddTreatments(TreatmentView model)
{
using(var treatment = new TreatmentRepository())
{
var treat = new PhysiqueData.ModelClasses.Treatment()
{
treatmentID = model.treatmentID,
treatmentCost = model.treatmentCost,
treatmentDuration = model.treatmentDuration,
treatmentName = model.treatmentName
}
treatment.Insert(treat);
}
}
This is my repository used in the service layer
public class TreatmentRepository:ITreatmentRepository
{
private ApplicationDbContext _datacontext;
private readonly IRepository<Treatment> _treatmentRepository;
public TreatmentRepository()
{
_datacontext = new ApplicationDbContext();
_treatmentRepository = new RepositoryService<Treatment>(_datacontext);
}
public void Insert(Treatment model)
{
_treatmentRepository.Insert(model);
}
}
The next code is my actual unit test for my treatment and it is not working,
please can I get some guidance on it. I googled a lot of things and still can't get it right.
[TestClass]
public class UnitTest1
{
[TestMethod]
public void AddingTreatmenttodatabase()
{
//var business = new TreatmentBusiness(new TreatmentRepository());
var treatment = new Treatment()
{
treatmentID = 1,
treatmentCost = 250,
treatmentDuration = 45,
treatmentName = "LowerBack"
};
var repositoryMock = new Mock<ITreatmentRepository>();
repositoryMock.Setup(x => x.Insert(treatment));
var business = new TreatmentBusiness(repositoryMock.Object);
business.AddTreatments(treatment);
repositoryMock.Verify(x => x.Insert(treatment), Times.Once());
}
}
So you're instantiating a mock of ITreatmentRepository, setting up some behaviour and injecting it into your TreatmentBusiness class. So far, so good.
But then, in your AddTreatments method, you're instantiating a new TreatmentRepository, instead of using the one injected in via the constructor.
I'm assuming your constructor looks something like this:
public class TreatmentBusiness
{
private readonly ITreatmentRepository repository;
public TreatmentBusiness(ITreatmentRepository repository)
{
this.repository = repository;
}
...
}
In which case, your method should look like this:
public void AddTreatments(TreatmentView model)
{
using (var treatment= this.repository)
{
var treat = new PhysiqueData.ModelClasses.Treatment();
{
treat.treatmentID = model.treatmentID;
treat.treatmentCost = model.treatmentCost;
treat.treatmentDuration = model.treatmentDuration;
treat.treatmentName = model.treatmentName;
}
treatment.Insert(treat);
}
}
Notice the usage of the field repository, as opposed to instantiating a new one.
As per Jimmy_keen's suggestion, in order to ensure your repository is properly instantiated and accessible throughout your class, a factory is advisable.
There are several ways you can achieve a repository factory, either you hand crank a dedicated factory and inject that into your constructor, like so:
public class TreatmentBusiness
{
private readonly ITreatmentRepositoryFactory repositoryFactory;
public TreatmentBusiness(ITreatmentRepositoryFactory repositoryFactory)
{
this.repositoryFactory = repositoryFactory;
}
...
}
And that change the way you access your repository like so:
public void AddTreatments(TreatmentView model)
{
using (var treatment= this.repositoryFactory.Make())
//or whatever method name you've chosen on your factory
If you feel this is too heavy handed, you can opt for a method delegate (Func<>) and inject just a method that instantiates a new TreatmentRepository.
This would change your constructor like so:
public class TreatmentBusiness
{
private readonly Func<TreatmentRepository> getTreatmentRepository;
public TreatmentBusiness(Func<TreatmentRepository> getTreatmentRepository)
{
this.getTreatmentRepository = getTreatmentRepository;
}
....
}
And you would change your method like this:
public void AddTreatments(string model)
{
using (var treatment = this.getTreatmentRepository()) //Or this.getTreatmentRepository.Invoke() - same thing
{
...
}
}
The way you resolve that dependency is up to you, either do it manually and inject that delegate like this when instantiating your Business object:
var treatmentBusiness = new TreatmentBusiness(() => new TreatmentRepository());
or you can use one of the many IoC containers/DI frameworks out there.
Related
I'm new to using Moq with Xunit in Visual Studio 2019.
I want to mock the contructor call of a class that is being called in the contructor of my tested class.
A simple demonstration of my problem:
public class MockedClass : IMockedClass
{
public MockedClass()
{
// don't call this
}
public List<string> Function1()
{ /* return a List<string> here */ }
}
public class MyClass
{
readonly IMockedClass mockedClass = null;
public MyClass()
{
mockedClass = new MockedClass();
}
public string Function2()
{ /* return a string here */ }
}
public class MyClassTest
{
[Fact]
public string Function2Test()
{
var returnMock = new List<string>() { "1", "2", "3" };
var mockMockedClass = new Mock<IMockedClass>();
mockMockedClass.Setup(x => x.Function1()).Returns(returnMock);
var myClass = new MyClass();
var result = myClass.Function2();
...
}
}
My problem is, that in the test Function2Test the constructor of MyClass is being called that calls the constructor of MockedClass.
But I don't want the constructor of MockedClass being called.
How can I mock the constructor of MockedClass?
I think you might need to slightly modify your code. You see, obtaining a mock of an interface by itself does not automatically change how other implementations behave when instantiated from other parts of code. You generally want to inject your mocked implementations into tested code via Dependency Injection.
public class MyClass
{
readonly IMockedClass mockedClass = null;
public MyClass(IMockedClass c)
{
mockedClass = c; // now you'll get the correct implemetation
}
public string Function2()
{ /* return a string here */ }
}
void Main()
{
var returnMock = new List<string>() { "1", "2", "3" };
var mockMockedClass = new Mock<IMockedClass>(); // get your mock here
mockMockedClass.Setup(x => x.Function1()).Returns(returnMock);
var myClass = new MyClass(mockMockedClass.Object); // inject it here
var result = myClass.Function2();
}
Then you will need to set up your Dependency Injection container to provide you with a concrete MockedClass when your actual application code runs. Depending on your code and requirements, there are heaps of options so I won't recommend a specific framework here.
Theoretically, you might be able to mock out the class in your current code structure. I could potentially see how you either opt for Fakes or fancy reflection techniques. However it likely will be way to much effort for going against what seems to be community-accepted best practice.
You were on the right direction to mock dependencies, but you lack the implementation of the Dependency Inversion Principle.
With your code as-is, you are tying your MyClass to the MockedClass, and furthermore you let MyClass control the MockedClass object's lifetime.
What you should do, is alter the constructor of MyClass to accept an IMockedClass object. Note that you should pass the interface, not the class type.
public class MyClass
{
readonly IMockedClass mockedClass = null;
public MyClass(IMockedClass mockedClass)
{
this.mockedClass = mockedClass();
}
public string Function2()
{ /* return a string here */ }
}
and your test code will be:
public string Function2Test()
{
var returnMock = new List<string>() { "1", "2", "3" };
var mockMockedClass = new Mock<IMockedClass>();
mockMockedClass.Setup(x => x.Function1()).Returns(returnMock);
var myClass = new MyClass(mockMockedClass.Object);
var result = myClass.Function2();
...
}
I have the following concrete class
public class Service
{
private IRepository _rep;
public Service(IRepository rep)
{
_rep() = rep;
}
public Boolean Foo(Int32 param1)
{
_rep.Foo(param1);
}
public void Bar()
{
_rep.Bar();
}
}
I have created the following shim for it.
using (ShimsContext.Create())
{
ShimService shimService = new ShimService()
{
FooInt32 = (param1) => { return true; },
};
}
I want foo to always return true. This works.
I want Bar to operate normally. This doesn't work.
When I debug _rep is null so I believe I need to pass this an IRepository into the Shims constructor but I can't work out how to do it.
I found the solution. You have to create an instance of the Service you want to Shim which includes the injection of IRepository and pass that that service into the Shim.....so
IRepository rep = new Repository();
Service service = new Service(rep);
ShimSignOffService shimService = new ShimSignOffService(service)
{
IsBookmarkProcessedInt32 = (bookmarkId) => { return true; },
};
I have a service class, it creates a new concrete PropertyClass, before doing action. I'm trying to test if DoSomething() was run.
Is it possible to create stud and control the returned Property value to a mock object?
public class ServiceClass
{
public PropertyClass Property {set; get;}
public void Action()
{
Property = new PropertyClass();
Property.DoSomething();
}
}
[Test] // This test does not work.
public class Action_Test
{
var service = new ServiceClass();
var mockPropertyClass = MockRepository.GenerateMock<IPropertyClass>();
service.Property.Stub(x=> new PropertyClass()).Return(mockPropertyClass);
service.Action();
service.Property.AssertWasCalled(x => x.DoSomething());
}
No. But you could easily mitigate this problem with factory design pattern. Consider:
public class ServiceClass
{
private readonly IPropertyClassFactory factory;
public PropertyClass Property { get; private set; }
public ServiceClass(IPropertyClassFactory factory)
{
this.factory = factory;
}
public void Action()
{
Property = factory.CreateInstance();
Property.DoSomething();
}
}
In test you create mocked factory which returns mocked object. Like this:
[Test]
public class Action_Test
{
var factoryMock = MockRepository.GenerateMock<IPropertyClassFactory>();
var propertyMock = MockRepository.GenerateMock<IPropertyClass>();
factoryMock.Stub(f => f.CreateInstance()).Returns(propertyMock);
var service = new ServiceClass(factoryMock);
service.Action();
propertyMock.AssertWasCalled(x => x.DoSomething());
}
Note that when factory is this simple, you might just as well use Func<IPropertyClass> instead of creating extra class/interface pair.
Your Action method is creating its own instance of PropertyClass which is overwriting your stub.
public void Action()
{
if (Property == null)
Property = new PropertyClass();
Property.DoSomething();
}
A nice way around having to check each time you use Property property, would be to assign the property in the constructor.
public ServiceClass() {
Property = new PropertyClass();
}
Then the Action method would just be:
public void Action()
{
Property.DoSomething();
}
I have a dependency being injected via Func<Owned<OwnedDependency>>. One of its dependencies requires a parameter that I will only have at the point of constructing OwnedDependency.
public class OwnedDependency
{
public OwnedDependency(IDependency1 dependency)
{
}
}
public interface IDependency1
{
}
public class Dependency1 : IDependency1
{
public Dependency1(MyParameter parameter)
{
}
}
public class MyClass
{
private readonly Func<Owned<OwnedDependency>> m_ownedDependencyFactory;
public MyClass(Func<Owned<OwnedDependency>> ownedDependencyFactory)
{
m_ownedDependencyFactory = ownedDependencyFactory;
}
public void CreateOwnedDependency()
{
var parameter = new MyParameter(...);
// ** how to setup parameter with the container? **
using (var ownedDependency = m_ownedDependencyFactory())
{
}
}
}
I can't work out a clean way of setting up the instance of MyParameter.
One approach I have explored is to inject ILifetimeScope into MyClass and then do something like:
var parameter = new MyParameter(...);
using (var newScope = m_lifetimeScope.BeginLifetimeScope())
{
newScope.Resolve<IDependency1>(new TypedParameter(typeof(MyParameter), parameter));
var ownedDependency = newScope.Resolve<OwnedDependency>();
// ...
}
but the container is becoming unnecessarily intrusive. Ideally what I would like to do is inject Func<IDependency1, Owned<OwnedDependency>> and the container be willing to use parameters passed in to satisfy any necessary dependency, not just the ones on OwnedDependency.
What about doing the resolution in two steps with using another factory for IDependency1:
public class MyClass
{
private Func<MyParameter, IDependency1> dependency1Factory;
private Func<IDependency1, Owned<OwnedDependency>> ownedDependencyFactory;
public MyClass(
Func<MyParameter, IDependency1> dependency1Factory,
Func<IDependency1, Owned<OwnedDependency>> ownedDependencyFactory)
{
this.dependency1Factory = dependency1Factory;
this.ownedDependencyFactory = ownedDependencyFactory;
}
public void CreateOwnedDependency()
{
var parameter = new MyParameter();
using (var owned = ownedDependencyFactory(dependency1Factory(parameter)))
{
}
}
}
I have the following method;
public class MyClass
{
public Repository UserRepository { get; set; }
public void CreateUser(Message someMsg)
{
if (someMsg.CanCreate)
{
var obj = new object();
UserRepository.Save(obj)
}
}
}
In my test case, I used Moq to mock out the ObjRepository and I wanted to to call verify on the "Save()" method. However, the save method takes in a object that is created within the method under test, which I cannot mock.
Is there anyway around this using Moq? I am doing this wrong?
You can have the following setup on your mock:
objRepMock.Setup(or => or.Save(It.IsAny<object>()).Callback(obj => {
// Do asserts on the object here
}
marcind got the ball rolling but I thought I'd put more code in. Your test would look like this:
var objMock = new Mock<Repository>();
objMock.Setup(x=>x.Save(It.IsAny<object>)).Verifiable();
var myclass = new MyClass{Repository = objMock.object};
var mymessage = new Mock<Message>();
myclass.CreateUser(mymessage.object);
objMock.Verify(x=>x.Save(It.IsAny<object>), Times.AtLeastOnce);
You could use dependency injection.
public Repository ObjRepository { get; set;}
public void doStuff()
{
var obj = new object();
doStuff(obj);
}
public void doStuff(Object obj)
{
ObjRepository.Save(obj)
}