Modify return property value of mock object - c#

I've come across a problem when writing a unit test where in the method I'm calling it doesn't modify the mock object I've passed in. I'm not sure if there's just something obvious I'm missing?
I've setup the mock as follows:
var mockList = new List<Mock<IDocument>>();
for (int i = 0; i < 4; i++)
{
var mockDocument = new Mock<IDocument>();
mockDocument.Setup(t => t.DocumentNo).Returns(i.ToString());
mockList.Add(mockDocument);
}
mockDocumentRepository.Setup(x => x.GetDocuments(It.IsAny<string>(), It.IsAny<string>()))
.Returns(mockList.Select(m => m.Object).ToList());
In the executed method, if I attempt to modify another property on the mocked class (for example t.DocumentName) the value remains Null. Is there anyway to setup that property to accept a modification?
The reason I'm doing this is to test whether the collection of documents has been modified by another collection in the method. Not sure if there's better way's of doing this?

Moq will leave all methods unimplemented unless instructed to do otherwise, and that includes properties. If you use mockDocument.SetupProperty(doc => doc.DocumentName); it will implement the property as a regular auto-property. You can use mockDocument.SetupAllProperties() if you want all properties to be auto-implemented, but you'll still have to do it for every mock object.
You could also consider making a stub instead of a mock:
public class StubDocument : IDocument
{
public string DocumentNo { get; set; }
public string DocumentName { get; set; }
...
}
In general, I find that stubbing is often preferable to mocking when dealing with very simple interfaces, as seems to be the case with your IDocument.

Related

AutoFixture - Creation of "Valid" and "Invalid" instances and [AutoData]

I created following sample model:
internal sealed class Bike : IVehicle
{
public Bike(
Engine engineType,
WindowHue windowHue,
Vehicle transport,
ushort wheelsCount,
string name) =>
(EngineType, WindowHue, Transport, WheelsCount, Name) =
(engineType, windowHue, transport, wheelsCount, name);
public WindowHue WindowHue { get; }
public Engine EngineType { get; }
public Vehicle Transport { get; }
public ushort WheelsCount { get; }
public string Name { get; }
}
I'm currently writing unit tests for Bike validator and I would like to use AutoFixture to create instances of Bike class that have values that are considered valid and invalid. Is there a way to instruct AutoFixture how to create those types of instances and tell it to fetch valid or invalid one depending on unit test that is running? For example: in test case that checks whether valid instance of Bike class passes validation I would like AutoFixture to create a valid Bike instance.
I attempted to achieve this behavior by creation of custom specimen builders but it seems that the last one that is registered is used to create an actual instance of requested type. Other idea was to create builder class that would use AutoFixture to create valid and invalid instances [via "Create" method] and use it in test cases, but I think that is not a good idea, since it leads to creation of redundant code [builder class per tested model].
If above behavior is possible, then is there a way to create such instances by using [AutoData] attribute, so that I don't have to call AutoFixture in test case body?
Yes you can, however the complexity of your setup code will depend on the complexity of your domain.
You could declare a customization that would build your DTO models with valid data, then use it via a custom [AutoData] attribute, and inside the test customize some of the DTOs with invalid data using .Customize<T>() or .Build<T>().
Now if you want to provide your invalid DTOs from the test parameters you could try to implement a [Invalid] attribute, that would customize individual test parameters, then use [Frozen] to use the value in other generated models.
For the [Invalid] attribute you can implement either the CustomizeAttribute from the AutoFixture.NUnit3 package or the IParameterCustomizationSource from AutoFixture.
As you'll see the output of the customization attribute is an ICustomization meaning inside the attribute you'll likely have a dictionary that outputs a customization for an invalid entity depending on the parameter type.
NB: I would really advise you use the first approach since it makes it obvious in what way the input data is invalid and makes asserting the results easier.
I would probably leave automapper out of this and create a class that takes care of creating the different types (invalid or valid) of objects that tests need:
Enums.cs
public enum BikeType
{
Valid,
Invalid
}
BikeCreator.cs
public static class BikeCreator
{
private Bike CreateValidBike()
{
return new Bike() //make this object "valid"
}
private Bike CreateInvalidBike()
{
return new Bike(); //make this object "invalid"
}
public Bike CreateInstance(BikeType bikeType)
{
Bike bike = null;
switch (bikeType)
{
case BikeType.Valid:
user = CreateValidBike();
break;
case BikeType.Invalid:
user = CreateInvalidBike();
break;
};
return bike;
}
}
That allows me to call that class in the following way:
//arrange
var invalidBike = BikeCreator.CreateInstance(BikeType.Invalid);
var validBike = BikeCreator.CreateInstance(BikeType.Valid);
This could be a good boilerplate to refactor into something more fancy with interfaces and generics. Sometimes "premature optimization is the root of all evil"

Moq setup returns reference to object

Let's say I have a simple class called MyRequestHandler, and it has a method called ProcessRequest that simply takes a request object, maps it to a return object and returns that object. (This is obviously a very simple example of a much more complex method/test that I'm working on).
public class MyRequestHandler
{
private IMapper _mapper;
public MyRequestHandler(IMapper maper)
{
_mapper = mapper;
}
public MyReturnObject ProcessRequest(MyRequestObject requestObject)
{
MyReturnObject returnObject = _mapper.Map<MyReturnObject>(requestObject);
return returnObject;
}
}
Now for unit testing (using Xunit), I want to test the ProcessRequest method, but obviously want to Moq the Map method, as such:
MyRequestObject requestObject = new RequestObject()
{
RequestInt = 1,
RequestString = "Hello"
};
MyReturnObject returnObject = new MyReturnObject()
{
MyInt = 1,
MyString = "Hello"
};
Mock<IMapper> mockMapper = new Mock<IMapper>();
mockMapper.Setup(m => m.Map<MyRequestObject>(requestObject)).Returns(returnObject);
MyRequestHandler requestHandler = new MyRequestHandler(mockMapper.Object);
MyReturnObject response = requestHandler.ProcessRequest(requestObject);
Assert.Equal(returnObject.MyInt, response.MyInt);
Assert.Equal(returnObject.MyString, response.MyString);
The problem here is that Moq returns (and I guess it should be obvious that it is) a reference to returnObject, so my Asserts will always pass, even if my method were to change a value prior to returning the object. Now I could instantiate a new MyReturnObject in the Moq Setup/Return and compare the MyInt and MyString by the values I give to the new one, but what if it's a really complex object with 20 properties and lists of objects? Maybe I want to use AutoFixture to create the object being returned and use DeepEqual to compare them? Is this even possible? Am I looking at this wrong, or do I have to do some type of cloning in the Setup/Return to make this work?
I don't believe there is built in functionality to detect that method under test did not change object passed to it.
Options:
make sure that return objects are immutable - either by having them immutable to start with or by returning interface without "set" methods with an instance created via mocks
create separate instance for "expected" and "mocked" values and then compare property-by-property. There are plenty of helper libraries to do so (I like FluentAssertions).
just assert on individual properties instead of comparing objects - works fine for small number of fields.
If possible I'd prefer immutable objects - that prevent possibility of writing wrong code and thus decreases amount of testing needed.
In this case you didn't receive a new data and can verify behavior
Internal state is not valuable in this case
var requestObject = new RequestObject();
var returnObject = new MyReturnObject();
...
var actual = requestHandler.ProcessRequest(requestObject);
Assert.AreSame(returnObject, actual);
mockMapper.Verify(
instance => instance.Map<MyRequestObject>(requestObject),
Times.Once);
Some details
we can't share write access with others, so i assume you have
public class MyRequestObject
{
int RequestInt { get; private set; }
string RequestString { get; private set; }
}
otherwise you always should test for parameter mutation. You can imagine 10 participants called in depth and each of them should have such tests. These tests will weak against changes, they do nothing with new properties.
It is better to have good coding convention and do codereview sometimes. In example someone can randomly remove private from property and it can't be catched with any tests.
There are many good practices in example "write test before of code" and so on

Moq - Non-overridable members may not be used in setup / verification expressions

I'm new to Moq. I'm mocking a PagingOptions class. Here is how the class looks like:
public class PagingOptions
{
[Range(1, 99999, ErrorMessage = "Offset must be greater than 0.")]
public int? Offset { get; set; }
[Range(1, 100, ErrorMessage = "Limit must be greater than 0 and less than 100.")]
public int? Limit { get; set; }
public PagingOptions Replace(PagingOptions newer)
{
return new PagingOptions
{
Offset = newer.Offset ?? Offset,
Limit = newer.Limit ?? Limit
};
}
}
Here is my mock version of the class,
var mockPagingOptions = new Mock<PagingOptions>();
mockPagingOptions.Setup(po => po.Limit).Returns(25);
mockPagingOptions.Setup(po => po.Offset).Returns(0);
I get the below error when setting up the property values. Am I making something wrong. Looks like I cannot Moq concrete class? Only Interfaces can be Mocked? Please assist.
Thanks,
Abdul
Moq creates an implementation of the mocked type. If the type is an interface, it creates a class that implements the interface. If the type is a class, it creates an inherited class, and the members of that inherited class call the base class. But in order to do that it has to override the members. If a class has members that can't be overridden (they aren't virtual, abstract) then Moq can't override them to add its own behaviors.
In this case there's no need to mock PagingOptions because it's easy to use a real one. Instead of this:
var mockPagingOptions = new Mock<PagingOptions>();
mockPagingOptions.Setup(po => po.Limit).Returns(25);
mockPagingOptions.Setup(po => po.Offset).Returns(0);
Do this:
var pagingOptions = new PagingOptions { Limit = 25, Offset = 0 };
How do we determine whether or not to mock something? Generally speaking, we mock something if we don't want to include the concrete runtime implementation in our test. We want to test one class not both at the same time.
But in this case PagingOptions is just a class that holds some data. There's really no point in mocking it. It's just as easy to use the real thing.
I had the same error, but in my case I was trying to mock the class itself and not its interface:
// Mock<SendMailBLL> sendMailBLLMock = new Mock<SendMailBLL>(); // Wrong, causes error.
Mock<ISendMailBLL> sendMailBLLMock = new Mock<ISendMailBLL>(); // This works.
sendMailBLLMock.Setup(x =>
x.InsertEmailLog(
It.IsAny<List<EmailRecipient>>(),
It.IsAny<List<EmailAttachment>>(),
It.IsAny<string>()));
In case you reached this question based on the original title Non-overridable members may not be used in setup / verification expressions and none of the other answers have helped you may want to see if reflection can satisfy your test needs.
Suppose you have a class Foo with a property defined as public int I { get; private set; }
If you try the various methods in the answers here few of them will work for this scenario. However you can use .net reflection to setup a value of an instance variable and still keep fairly good refactoring support in the code.
Here is a snippet that sets a property with a private setter:
var foo = new Foo();
var I = foo.GetType().GetProperty(nameof(Foo.I), BindingFlags.Public | BindingFlags.Instance);
I.SetValue(foo, 8675309);
I do not recommend this for production code. It has proven very useful in numerous tests for me. I found this approach a few years ago but needed to look it up again recently and this was the top search result.
I want to improve Scott's answer and give a general answer
If the type is a class, it creates an inherited class, and the members of that inherited class call the base class. But in order to do that it has to override the members. If a class has members that can't be overridden (they aren't virtual, abstract) then Moq can't override them to add its own behaviors.
In my situation i had to make the prop virtual. So answer to your class code is:
public class PagingOptions {
[Range (1, 99999, ErrorMessage = "Offset must be greater than 0.")]
public virtual int? Offset { get; set; }
[Range (1, 100, ErrorMessage = "Limit must be greater than 0 and less than 100.")]
public virtual int? Limit { get; set; }
public PagingOptions Replace (PagingOptions newer) {
return new PagingOptions {
Offset = newer.Offset ?? Offset,
Limit = newer.Limit ?? Limit
};
}
}
use same:
var mockPagingOptions = new Mock<PagingOptions>();
mockPagingOptions.Setup(po => po.Limit).Returns(25);
mockPagingOptions.Setup(po => po.Offset).Returns(0);
On occasion you may be working with a class from a third party library that has properties which can be directly set or mocked.
Where the answer by above is not sufficient you can also invoke the setter method directly, for example where a class has a property called "Id" with no accessible setter:
var idSetter = account.GetType().GetMethod("set_Id", BindingFlags.Instance | BindingFlags.NonPublic);
idSetter!.Invoke(account, new[] { "New ID Here" });
In my case I was mocking a public method which was not virtual. Making the method virtual made the trick.
As an old Java developer, I'm used to the approach that all public methods are already virtual, there is no need to mark them separately as virtual so that sub classes can override them. C# is different here.
Maybe someone can explain if it is ok to mark a public method in a production code as virtual for testing purposes in C#.

Automate the testing of property assignments in constructor

In my domain layer I create a lot of classes which looks like this
public class Route
{
public Route(Location origin, Location destination)
{
this.Origin = origin;
this.Destination = destination;
}
public Location Origin { get; }
public Location Destination { get; }
}
Now I need to unit-test this constructor
[Test]
public void PropertiesAreAssigned()
{
var origin = new Location(...);
var destination = new Location(...);
var route = new Route(origin, destination);
route.Origin.Should().Be(origin);
route.Destination.Should().Be(destination);
}
I have quite a few of those classes and tests which are very similar to each other. What I'd like is to have some kind of method which just accepts the type arguments, and then does all the testing for me, i.e.
instantiate a variable per constructor parameter (with whole graph of dependencies needed)
pass these variables to constructor
checks that the property values are assigned correctly
I'm pretty sure I can do this with a bit of reflection, but maybe is there an existing library for doing that? More tests are welcome, e.g.
Testing the null argument throws the proper exception
Testing that Equals and GetHashCode are implemented correctly
For me testing a simple constructor, simple accessors and mutators are a bad practice... It will be covered with behavioral (with intention) test. The less you test implementation details, the more your tests will be robust and resist to changes.
Testing constructor with complex behavior can be useful. But I often try to don't have any complex behavior in my constructors ^^

Mocking objects with different constructors

I am trying to understand why mocking behaves in such a way (I'm using NUnit with Moq). Let's say, we have a simple class:
public class Package
{
public virtual int PackageId { get; set; }
public Package()
:this(-1)
{
}
public Package(int packageId)
{
PackageId = packageId;
}
}
And some simple tests to discuss:
[TestFixture]
public class NUnitTrickyTest
{
private const int SamplePackageId = 10;
[Test]
public void TestPackageSetUp_WhenMockedWithDefaultConstructor_ExpectSamplePackageIdSet()
{
var samplePackage = new Mock<Package>();
samplePackage.SetupProperty(x => x.PackageId, SamplePackageId);
Assert.AreEqual(SamplePackageId, samplePackage.Object.PackageId);
}
[Test]
public void TestPackageSetUp_WhenMockedWithParametrizedConstructor_ExpectSamplePackageIdSet()
{
var samplePackage = new Mock<Package>(SamplePackageId);
// samplePackage.SetupProperty(x => x.PackageId, SamplePackageId);
Assert.AreEqual(SamplePackageId, samplePackage.Object.PackageId);
}
}
The first test fails as samplePackage.Object.PackageId returns -1, not 10 as expected. As I understand mocked Package() calls parameterized constructor which initializes the property with default -1. In the second test we find samplePackage.Object.PackageId returning 0.
The first thing I don't understand why 0 was returned (in debug I saw that 10 was passed in the constructor, but the property remained 0 value). The second one: if we uncomment this command samplePackage.SetupProperty(x => x.PackageId, SamplePackageId) in the second test, it will succeed. So why SetupProperty behaves as expected in that case (property returns 10), and not in such a way in the first test?
Could you please help? This is my first post so don't be severe :)
All mockable (virtual) methods use a proxy by default, so that is why you get a default value (0) on the second test (the proxy is not set). You can get around this by setting CallBase = true on your mock, though.
CallBase = true will use default implementations if available instead of trying to mock everything out.
It took me a second to figure out the reason for the first one failing and I believe that this is because SetupProperty only turns on tracking with a default value and since you are overriding that default value in the constructor then that is what is used. If you want to force a value then you need to use Setup(x=>x.PackageId).Returns(SamplePackageId) or SetupGet

Categories

Resources