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();
...
}
Related
I got a class which looks like below
public interface ILocationProvider
{
bool IsRequiredLocation (string type);
}
public class MyClass : IMyInterface
{
private readonly IEnumerable<ILocationProvider> _locationProvider;
public MyClass (ILocationProvider[] locationProvider)
{
_locationProvider = locationProvider;
}
public ILocationProvider ProvideRequireLocationObject(string type)
{
ILocationProvider location = _locationProvider.FirstOrDefault(x => x.IsRequiredLocation(type));
return location;
}
}
Now I am trying to write some tests for it. But I stuck passing the Mock<IEnumerable<ITransitReportCountryFlowProvider>> to constructor. Below my test code
[TestClass]
public class TMyClassTest
{
private Mock<IEnumerable<ILocationProvider>> _locationProvider = null;
private IMyInterface _myClass = null;
[TestInitialize]
public void InitializeTest ()
{
_locationProvider = new Mock<IEnumerable<ILocationProvider>>();
}
[TestMethod]
public void ProvideRequireLocationObject_Test1()
{
//Given: I have type as 'PMI'
string type = "PMI";
//When: I call MyClass object
_myClass = new MyClass(_locationProvider.Object); //wrong actual argument as the formal argument is an array of ILocationProvider
//_locationProvider.Setup(x => x.IsRequiredCountryFlow(It.IsAny<string>())).Returns(true); //how do I setup
ILocationProvider result = _myClass.ProvideRequireLocationObject(type);
//Then: I get a type of ILocationProvider in return
Assert.IsTrue(result is ILocationProvider);
}
}
Problem 1: The line _myClass = new MyClass(_locationProvider.Object) in above test class, as the constructor's formal argument is ILocationProvider[] so I cannot pass a mocking object of Mock<IEnumerable<ILocationProvider>>
Problem 2: If I change the line private readonly IEnumerable<ILocationProvider> _locationProvider; in above MyClass to private readonly ILocationProvider[] _locationProvider; I will not be able to mock it as because mock must be an interface or an abstract or non-sealed class.
Problem 3: How do I set up for _locationProvider.FirstOrDefault(x => x.IsRequiredLocation(type)); in my test method
Problem 4: How do I assert that my method ProvideRequireLocationObject is returning a type of ILocationProvider
First of all, you don’t need to mock the collection. Collections (arrays or lists) are tested well enough to trust on their implementation. Since your constructor expects an array, you need to pass an array. And the simplest way to do that is to simply pass an array. There is no reason to mock this at all.
Changing the implementation details of the class you are testing (as suggested in problem 2) will not change anything on the testing surface. Unit tests should always be independent from the internal implementation details anyway.
How do I assert that my method ProvideRequireLocationObject is returning a type of ILocationProvider
You don’t need to do that. The method has that return type, so the compiler will only accept an implementation where the method returns that type. You are guaranteed by the language that if there is a return value, then it’s of the ILocationProvider type. So you actually just need to check for null.
Taking your implementation, below is a possible way to test this. Note that you don’t actually need to mock this. You usually mock things when the actual implementation is too difficult to set up (e.g. has other dependencies) or when providing a testable implementation is too much work (e.g. an interface with lots of method but you only need one). In this case, I’m assuming that the ILocationProvider is easy to implement, so we’re going to create a test type for this:
[TestClass]
public class MyClassTests
{
[TestMethod]
public void ProvideRequireLocationObject_EmptyCollection()
{
// arrange
var providers = new ILocationProvider[] {};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.IsNull(result);
}
[TestMethod]
public void ProvideRequireLocationObject_NoRequiredLocation()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(false)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.IsNull(result);
}
[TestMethod]
public void ProvideRequireLocationObject_OneRequiredLocation()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(true)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.AreEqual(providers[0], result);
}
[TestMethod]
public void ProvideRequireLocationObject_OneRequiredLocationNotFirstInArray()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(false),
new TestLocationProvider(true),
new TestLocationProvider(false)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.AreEqual(providers[1], result);
}
[TestMethod]
public void ProvideRequireLocationObject_MultipleRequiredLocations()
{
// arrange
var providers = new ILocationProvider[] {
new TestLocationProvider(true),
new TestLocationProvider(true),
new TestLocationProvider(true)
};
var obj = new MyClass(providers);
// act
var result = obj.ProvideRequireLocationObject();
// assert
Assert.AreEqual(providers[0], result);
}
public class TestLocationProvider : ILocationProvider
{
public TestLocationProvider(bool isRequiredLocation)
{
IsRequiredLocation = isRequiredLocation;
}
public bool IsRequiredLocation { get; private set; }
}
}
Of course, you could expand those tests as necessary.
I believe are looking at it from the wrong angle. I think you don't need to mock the IEnumerable (Mock<IEnumerable<ITransitReportCountryFlowProvider>>) - IEnumerable has been testing front and back and besides you don't want to have to implement all its logic..
I think you should mock your own classes: Mock<ITransitReportCountryFlowProvider>
And pass a normal IEnumerable containing your mock in it
Something like:
[TestClass]
public class TMyClassTest
{
private Mock<ILocationProvider> _locationProvider = null;
private IEnumerable<ILocationProvider> _locationProviderCollection;
private IMyInterface _myClass = null;
[TestInitialize]
public void InitializeTest ()
{
_locationProvider = new Mock<IEnumerable<ILocationProvider>>();
_locationProviderCollection = new List<ILocationProvider> { _locationProvider };
}
[TestMethod]
public void ProvideRequireLocationObject_Test1()
{
//Given: I have type as 'PMI'
string type = "PMI";
//When: I call MyClass object
_myClass = new MyClass(_locationProviderCollection); //wrong actual argument as the formal argument is an array of ILocationProvider
.....
}
}
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 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.
class Parent{
public string Name{ get; set; }
}
class Child :Parent{
public string address{ get; set; }
}
[TestClass]
class TestClass{
[TestMethod]
public void TestMethod()
{
var c = new Fakes.Child();
c.addressGet = "foo"; // I can see that
c.NameGet = "bar"; // This DOES NOT exists
}
}
How can I set the "name" in the above code sample?
The generated class for Parent will have a constructor that looks like: ShimParent(Parent p).
All you need to do is:
var child = new ShimChild();
var parent = new ShimParent(child);
And set the appropriate values on the respective Shim's.
You'll have to declare it on the base class. The easiest way is to call the base class its AllInstances property:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
ClassLibrary1.Child myChild = new ClassLibrary1.Child();
using (ShimsContext.Create())
{
ClassLibrary1.Fakes.ShimChild.AllInstances.addressGet = (instance) => "foo";
ClassLibrary1.Fakes.ShimParent.AllInstances.NameGet = (instance) => "bar";
Assert.AreEqual("foo", myChild.address);
Assert.AreEqual("bar", myChild.Name);
}
}
}
Also always try to add the ShimsContext to ensure the proper cleaning of your shim. Otherwise your other unit tests will also get the values returned that you have declared before.
Information on ShimsContext can be found here: http://msdn.microsoft.com/en-us/library/hh549176.aspx#ShimsContext
I've put together a solution based on previous answers, the Microsoft documentation, and my own experimentation. I've also changed the TestMethod a bit to show how I would actually use it for testing. Note: I haven't compiled this specific code, so I apologize if it doesn't work as is.
[TestClass]
class TestClass
{
[TestMethod]
public void TestMethod()
{
using (ShimsContext.Create())
{
Child child = CreateShimChild("foo", "bar");
Assert.AreEqual("foo", child.address); // Should be true
Assert.AreEqual("bar", child.Name); // Should be true
}
}
private ShimChild CreateShimChild(string foo, string bar)
{
// Create ShimChild and make the property "address" return foo
ShimChild child = new ShimChild() { addressGet = () => foo };
// Here's the trick: Create a ShimParent (giving it the child)
// and make the property "Name" return bar;
new ShimParent(child) { NameGet = () => bar };
return child;
}
}
I have no idea how the returned child knows that its Name should return "bar", but it does! As you can see, you don't even need to save the ShimParent anywhere; it's only created in order to specify the value for the Name property.
None of the suggested approaches so far would work in my opinion. After a lot of trial and error I have come up with this below code which worked for me. Basically you will have to define a delegate that initializes your child class and within that delegate you hookup a Shim of parent that your child class should inherit from.
public void TestMethod()
{
//var c = new Fakes.Child();
//c.addressGet = "foo"; // I can see that
//c.NameGet = "bar"; // This DOES NOT exists
using (ShimsContext.Create())
{
ShimChild childShim = null;
ShimChild.Constructor = (#this) =>
{
childShim = new ShimChild(#this);
// the below code now defines a ShimParent object which will be used by the ShimChild object I am creating here
new ShimParent()
{
NameSetString = (value) =>
{
//do stuff here
},
NameGet = () =>
{
return "name";
}
};
};
}
}
I encountered a class during my work that looks like this:
public class MyObject
{
public int? A {get; set;}
public int? B {get; set;}
public int? C {get; set;}
public virtual int? GetSomeValue()
{
//simplified behavior:
return A ?? B ?? C;
}
}
The issue is that I have some code that accesses A, B and C and calls the GetSomeValue() method (now, I'd say this is not a good design, but sometimes my hands are tied ;-)). I want to create a mock of this object, which, at the same time, has A, B and C set to some values. So, when I use moq as such:
var m = new Mock<MyObject>() { DefaultValue = DefaultValue.Mock };
lets me setup a result on GetSomeValue() method, but all the properties are set to null (and setting up all of them using Setup() is quite cumbersome, since the real object is a nasty data object and has more properties than in above simplified example).
So on the other hand, using AutoFixture like this:
var fixture = new Fixture();
var anyMyObject = fixture.CreateAnonymous<MyObject>();
Leaves me without the ability to stup a call to GetSomeValue() method.
Is there any way to combine the two, to have anonymous values and the ability to setup call results?
Edit
Based on nemesv's answer, I derived the following utility method (hope I got it right):
public static Mock<T> AnonymousMock<T>() where T : class
{
var mock = new Mock<T>();
fixture.Customize<T>(c => c.FromFactory(() => mock.Object));
fixture.CreateAnonymous<T>();
fixture.Customizations.RemoveAt(0);
return mock;
}
This is actually possible to do with AutoFixture, but it does require a bit of tweaking. The extensibility points are all there, but I admit that in this case, the solution isn't particularly discoverable.
It becomes even harder if you want it to work with nested/complex types.
Given the MyObject class above, as well as this MyParent class:
public class MyParent
{
public MyObject Object { get; set; }
public string Text { get; set; }
}
these unit tests all pass:
public class Scenario
{
[Fact]
public void CreateMyObject()
{
var fixture = new Fixture().Customize(new MockHybridCustomization());
var actual = fixture.CreateAnonymous<MyObject>();
Assert.NotNull(actual.A);
Assert.NotNull(actual.B);
Assert.NotNull(actual.C);
}
[Fact]
public void MyObjectIsMock()
{
var fixture = new Fixture().Customize(new MockHybridCustomization());
var actual = fixture.CreateAnonymous<MyObject>();
Assert.NotNull(Mock.Get(actual));
}
[Fact]
public void CreateMyParent()
{
var fixture = new Fixture().Customize(new MockHybridCustomization());
var actual = fixture.CreateAnonymous<MyParent>();
Assert.NotNull(actual.Object);
Assert.NotNull(actual.Text);
Assert.NotNull(Mock.Get(actual.Object));
}
[Fact]
public void MyParentIsMock()
{
var fixture = new Fixture().Customize(new MockHybridCustomization());
var actual = fixture.CreateAnonymous<MyParent>();
Assert.NotNull(Mock.Get(actual));
}
}
What's in MockHybridCustomization? This:
public class MockHybridCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new MockPostprocessor(
new MethodInvoker(
new MockConstructorQuery())));
fixture.Customizations.Add(
new Postprocessor(
new MockRelay(t =>
t == typeof(MyObject) || t == typeof(MyParent)),
new AutoExceptMoqPropertiesCommand().Execute,
new AnyTypeSpecification()));
}
}
The MockPostprocessor, MockConstructorQuery and MockRelay classes are defined in the AutoMoq extension to AutoFixture, so you'll need to add a reference to this library. However, note that it's not required to add the AutoMoqCustomization.
The AutoExceptMoqPropertiesCommand class is also custom-built for the occasion:
public class AutoExceptMoqPropertiesCommand : AutoPropertiesCommand<object>
{
public AutoExceptMoqPropertiesCommand()
: base(new NoInterceptorsSpecification())
{
}
protected override Type GetSpecimenType(object specimen)
{
return specimen.GetType();
}
private class NoInterceptorsSpecification : IRequestSpecification
{
public bool IsSatisfiedBy(object request)
{
var fi = request as FieldInfo;
if (fi != null)
{
if (fi.Name == "__interceptors")
return false;
}
return true;
}
}
}
This solution provides a general solution to the question. However, it hasn't been extensively tested, so I'd love to get feedback on it.
Probably there is a better why, but this works:
var fixture = new Fixture();
var moq = new Mock<MyObject>() { DefaultValue = DefaultValue.Mock };
moq.Setup(m => m.GetSomeValue()).Returns(3);
fixture.Customize<MyObject>(c => c.FromFactory(() => moq.Object));
var anyMyObject = fixture.CreateAnonymous<MyObject>();
Assert.AreEqual(3, anyMyObject.GetSomeValue());
Assert.IsNotNull(anyMyObject.A);
//...
Initially I tried to use fixture.Register(() => moq.Object); instead of fixture.Customize but it registers the creator function with OmitAutoProperties() so it wouldn't work for you case.
As of 3.20.0, you can use AutoConfiguredMoqCustomization. This will automatically configure all mocks so that their members' return values are generated by AutoFixture.
var fixture = new Fixture().Customize(new AutoConfiguredMoqCustomization());
var mock = fixture.Create<Mock<MyObject>>();
Assert.NotNull(mock.Object.A);
Assert.NotNull(mock.Object.B);
Assert.NotNull(mock.Object.C);