How do I get shims for base classes using Microsoft Fakes? - c#

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";
}
};
};
}
}

Related

Unit Testing a Class With A Private Constructor

I am trying to test a class that only has a private constructor. This is for a course registration system. The courses do not get create via our application, therefore we intentionally have no public constructor. Instead we use EF to get the courses that are already in the database, and register students to them.
I am trying to test the register method of the Course class, however I have no way of creating an instance. I could use
course = (Course)Activator.CreateInstance(typeof(Course), true);, but then I don't have a way to setup the necessary properties since those are private.
What is the recommended approach for unit testing without a constructor?
This is a slimmed down version of the code.
public class Course
{
private Course()
{
}
public int Id { get; private set; }
public string Name { get; private set; }
public bool Open { get; private set; }
public virtual ICollection<Student> Students { get; private set; }
public void Register(string studentName)
{
if (Open)
{
var student = new Student(studentName);
Students.Add(student);
}
}
}
// Usage //
using (var db = new SchoolContext())
{
var course = db.Courses.Include(x => x.Students).Where(x => x.Name == courseName).First();
course.Register(studentName);
db.SaveChanges();
}
// Unit Test //
[Fact]
public void CanRegisterStudentForOpenClass(){
// HERE I HAVE NO WAY TO CHANGE THE OPEN VARIABLE
var course = (Course)Activator.CreateInstance(typeof(Course), true);
course.Register("Bob");
}
Yes you can using reflexion. your code is neraly there;
you can get properties and fields of the types with typeof(Course).GetProperty("PropertyName") then you can use SetValue to set the desired value, and pass as parameter first the instance to modify then the value.
in your case true;
note: in your example you will need to add the Collection of students too, if your Open is true.
Here there is a working example:
[Fact]
public void CanRegisterStudentForOpenClass()
{
var course = (Course)Activator.CreateInstance(typeof(Course), true);
typeof(Course).GetProperty("Open").SetValue(course, true, null);
ICollection<Student> students = new List<Student>();
typeof(Course).GetProperty("Students").SetValue(course, students, null);
course.Register("Bob");
Assert.Single(course.Students);
}
If you would rather not use reflection, then I recommend you use internal classes (instead of private) and using the InternalsVisibleToAttribute on your implementation assembly.
You can find more about the attribute here. Here's a quick guide on how you can use it!
Step 1. Add this attribute to your assembly that wants its internal code tested.
[assembly: InternalsVisibleToAttribute("MyUnitTestedProject.UnitTests")]
Step 2. Change private to internal.
public class Course
{
internal Course()
{
}
public int Id { get; internal set; }
public string Name { get; internal set; }
public bool Open { get; internal set; }
public virtual ICollection<Student> Students { get; internal set; }
/* ... */
}
Step 3. Write your tests like normal!
[Fact]
public void CanRegisterStudentForOpenClass()
{
var course = new Course();
course.Id = "#####";
course.Register("Bob");
}
As a few people have mentioned here, unit testing something private is either a code smell, or a sign you're writing the wrong tests.
In this case, what you would want to do is use EF's in-memory database if you're using Core, or mocking with EF6.
For EF6 You can follow the docs here
I would say rather than newing your dbContext where you do, pass it in via Dependency Injection. If that's beyond the scope of the work you're doing, (I'm assuming this is actual coursework, so going to DI may be overkill) then you can create a wrapper class that takes a dbcontext and use that in place.
Taking a few liberties with where this code is called from...
class Semester
{
//...skipping members etc
//if your original is like this
public RegisterCourses(Student student)
{
using (var db = new SchoolContext())
{
RegisterCourses(student, db);
}
}
//change it to this
public RegisterCourses(Student student, SchoolContext db)
{
var course = db.Courses.Include(x => x.Students).Where(x => x.Name == courseName).First();
course.Register(studentName);
db.SaveChanges();
}
}
[Fact]
public void CanRegisterStudentForOpenClass()
{
//following after https://learn.microsoft.com/en-us/ef/ef6/fundamentals/testing/mocking#testing-query-scenarios
var mockCourseSet = new Mock<DbSet<Course>>();
mockCourseSet.As<IQueryable<Course>>().Setup(m => m.Provider).Returns(data.Provider);
mockCourseSet.As<IQueryable<Course>>().Setup(m => m.Expression).Returns(data.Expression);
mockCourseSet.As<IQueryable<Course>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockCourseSet.As<IQueryable<Course>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
//create an aditional mock for the Student dbset
mockStudentSet.As.........
var mockContext = new Mock<SchoolContext>();
mockContext.Setup(c => c.Courses).Returns(mockCourseSet.Object);
//same for student so we can include it
mockContext.Include(It.IsAny<string>()).Returns(mockStudentSet); //you can change the isAny here to check for Bob or such
var student = Institution.GetStudent("Bob");
var semester = Institution.GetSemester(Semester.One);
semester.RegisterCourses(student, mockContext);
}
If you're using EFCore you can follow it along from here
You can fake private constructors and members using TypeMock Isolator or JustMock (both paid) or using MS Fakes (only available in VS Enterprise).
There is also a free Pose library that allows you to fake access to properties.
Unfortunately, the private constructor can't be forged. Therefore, you will need to create an instance of the class using reflection.
Add package.
Open namespace:
using Pose;
Test code:
[Fact]
public void CanRegisterStudentForOpenClass()
{
var course = (Course)Activator.CreateInstance(typeof(Course), true);
ICollection<Student> students = new List<Student>();
Shim studentsPropShim = Shim.Replace(() => Is.A<Course>().Students)
.With((Course _) => students);
Shim openPropShim = Shim.Replace(() => Is.A<Course>().Open)
.With((Course _) => true);
int actual = 0;
PoseContext.Isolate(() =>
{
course.Register("Bob");
actual = course.Students.Count;
},
studentsPropShim, openPropShim);
Assert.Equal(1, actual);
}
You can create a JSON representation of your default instance and deserialize it with Newtonsoft.
Something like this:
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using privateConstructor;
namespace privateConstructorTest
{
[TestClass]
public class CourseTest
{
[TestMethod]
public void Register_WhenOpenIsTrue_EnableAddStudents()
{
// Arrange
const string json = #"{'Id': 1, 'name':'My Course', 'open':'true', 'students':[]}";
var course = CreateInstance<Course>(json);
// Act
course.Register("Bob");
// Assert
Assert.AreEqual(1, course.Students.Count);
}
[TestMethod]
public void Register_WhenOpenIsFalse_DisableAddStudents()
{
// Arrange
const string json = #"{'Id': 1, 'name':'My Course', 'open':'false', 'students':[]}";
var course = CreateInstance<Course>(json);
// Act
course.Register("Bob");
// Assert
Assert.AreEqual(0, course.Students.Count);
}
private static T CreateInstance<T>(string json) =>
JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings
{
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
ContractResolver = new ContractResolverWithPrivates()
});
public class ContractResolverWithPrivates : CamelCasePropertyNamesContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var prop = base.CreateProperty(member, memberSerialization);
if (prop.Writable) return prop;
var property = member as PropertyInfo;
if (property == null) return prop;
var hasPrivateSetter = property.GetSetMethod(true) != null;
prop.Writable = hasPrivateSetter;
return prop;
}
}
}
}
In order to have a cleaner test class, you can extract the JSON strings and the helper code that creates the instance.

C# testing - mock class in contructor call

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();
...
}

How to mock an IEnumerable<interface> type and pass it to constructor

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
.....
}
}

How to return null when accessing a moq object?

I am using Moq library for unit testing. Now what i want is that when I access my object for the first time it should return null, and when i access this on second time it should return something else.
here is my code
var mock = new Mock<IMyClass>();
mock.Setup(?????);
mock.Setup(?????);
var actual = target.Method(mock.object);
in my method i am first checking that whether mock object is null or not, if it is null then do initialize it and then do some calls on it.
bool Method(IMyClass myObj)
{
if (myObj != null)
return true;
else
{
myObj = new MyClass();
bool result = myObj.SomeFunctionReturningBool();
return result;
}
}
what to do setup for mock object,
Also i need to know how to mock this line
bool result = myObj.SomeFunctionReturningBool();
It sounds like you are trying to run two tests with one test method - maybe it would be better to split the tests into two?
You also want to initialise a new object if the method is passed null. To test this, I suggest creating a factory object responsible for creating instances of MyClass. The new code would look like:
interface IMyClassFactory
{
IMyClass CreateMyClass();
}
bool Method(IMyClass myObj, IMyClassFactory myClassFactory)
{
if (myObj != null)
{
return true;
}
myObj = myClassFactory.CreateMyClass();
return myObj.SomeFunctionReturningBool();
}
Then the tests would look like:
[Test]
public void Method_ShouldReturnTrueIfNotPassedNull()
{
Assert.That(target.Method(new MyClass()), Is.True);
}
[Test]
public void Method_ShouldCreateObjectAndReturnResultOfSomeFunctionIfPassedNull()
{
// Arrange
bool expectedResult = false;
var mockMyClass = new Mock<IMyClass>();
mockMyClass.Setup(x => x.SomeFunctionReturningBool()).Returns(expectedResult);
var mockMyFactory = new Mock<IMyClassFactory>();
mockMyFactory.Setup(x => x.CreateMyClass()).Returns(mockMyClass.Object);
// Act
var result = target.Method(null, mockMyFactory.Object);
// Assert
mockMyClass.Verify(x => x.SomeFunctionReturningBool(), Times.Once());
mockMyFactory.Verify(x => x.CreateMyClass(), Times.Once());
Assert.That(result, Is.EqualTo(expectedResult));
}
Here the factory pattern has been used to pass in an object which can create objects of IMyClass type, and then the factory itself has been mocked.
If you do not want to change your method's signature, then create the factory in the class's constructor, and make it accessible via a public property of the class. It can then be overwritten in the test by the mock factory. This is called dependency injection.
Moq - Return null - This working example simply illustrates how to return null using Moq. While the line of code is required is the commented line below, a full working example is provided below.
// _mockShopService.Setup(x => x.GetProduct(It.IsAny<string>())).Returns(() => null);
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
}
public interface IShopService
{
Product GetProduct(string productId);
}
public class ShopService : IShopService
{
public Product GetProduct(string productId)
{
if (string.IsNullOrWhiteSpace(productId))
{
return new Product();
}
return new Product { Id = "8160807887984", Name = "How to return null in Moq" };
}
}
public class Shop
{
private static IShopService _shopService;
public Shop(IShopService shopService)
{
_shopService = shopService;
}
public Product GetProduct(string productId)
{
Product product = _shopService.GetProduct(productId);
return product;
}
}
[TestClass]
public class ShopTests
{
Mock<IShopService> _mockShopService;
[TestInitialize]
public void Setup()
{
_mockShopService = new Mock<IShopService>();
}
[TestMethod]
public void ShopService_GetProduct_Returns_null()
{
//Arrange
Shop shop = new Shop(_mockShopService.Object);
//This is how we return null --- all other code above is to bring this line of code home
_mockShopService.Setup(x => x.GetProduct(It.IsAny<string>())).Returns(() => null);
//Act
var actual = shop.GetProduct(It.IsAny<string>());
//Assert
Assert.IsNull(actual);
}
}
To mock a result value you can do simply:
mock.Setup(foo => foo.SomeFunctionReturningBool()).Returns(true); // or false :)
for the other question, just pass null in the unit test instead of passing mock.object and your unit test cover that too. So you basically create two unit test one with:
var actual = target.Method(mock.object);
and the other one with:
var actual = target.Method(null);
Currently your SUT is tight-coupled with MyClass implementation. You can't mock objects which are instantiated with new keyword inside your SUT. Thus you cannot test your SUT in isolation, and your test is not unit test anymore. When implementation of MyClass.SomeFunctionReturningBool will change (it will return true instead of false), tests of your SUT will fail. This shouldn't happen. Thus, delegate creation to some dependency (factory) and inject that dependency to your SUT:
[Test]
public void ShouldReturnTrueWhenMyClassIsNotNull()
{
Mock<IMyClassFactory> factory = new Mock<IMyClassFactory>();
Mock<IMyClass> myClass = new Mock<IMyClass>();
var foo = new Foo(factory.Object);
Assert.True(foo.Method(myClass.Object));
}
[Test]
public void ShouldCreateNewMyClassAndReturnSomeFunctionValue()
{
bool expected = true;
Mock<IMyClass> myClass = new Mock<IMyClass>();
myClass.Setup(mc => mc.SomeFunctionReturningBool()).Returns(expected);
Mock<IMyClassFactory> factory = new Mock<IMyClassFactory>();
factory.Setup(f => f.CreateMyClass()).Returns(myClass.Object);
var foo = new Foo(factory.Object);
Assert.That(foo.Method(null), Is.EqualTo(expected));
factory.VerifyAll();
myClass.VerifyAll();
}
BTW assignment new value to method parameter does not affect reference which you passed to method.
Implementation:
public class Foo
{
private IMyClassFactory _factory;
public Foo(IMyClassFactory factory)
{
_factory = factory;
}
public bool Method(IMyClass myObj)
{
if (myObj != null)
return true;
return _factory.CreateMyClass().SomeFunctionReturningBool();
}
}
You can use TestFixture with parameter. this test will run two times and different type value.
using NUnit.Framework;
namespace Project.Tests
{
[TestFixture(1)]
[TestFixture(2)]
public class MyTest
{
private int _intType;
public MyTest(int type)
{
_intType = type;
}
[SetUp]
public void Setup()
{
if (_intType==1)
{
//Mock Return false
}
else
{
//Mock Return Value
}
}
}
}

Creating a hybrid of a mock and an anonymous object using e.g. Moq and AutoFixture?

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);

Categories

Resources