I want to mock a concrete class, to be specific SortedDictionary.
Context:
I have a LocationMapper class defined as below:
public class LocationMapper
{
private SortedDictionary<string, Location>() locationMap;
public LocationMapper()
{
this.locationMap = new SortedDictionary<string, Location>();
}
public LocationMapper(SortedDictionary<string, Location> locations)
{
this.locationMap = locations;
}
public Location AddLocation(Location location)
{
if(! locationMap.ContainsKey(location.Name))
{
locationMap.Add(location.Name, location)
}
return locationMap[location.Name];
}
}
To Unit Test AddLocation(), I need to Mock the concrete class SortedDictionary<>. Unfortunately, NSubstitute is not allowing it.
The unit test that I had envisioned to write is below
[Test]
public void AddLocation_ShouldNotAddLocationAgainWhenAlreadyPresent()
{
var mockLocationMap = ;//TODO
//Stub mockLocationMap.ContainsKey(Any<String>) to return "true"
locationMapper = new LocationMapper(mockLocationMap);
locationMapper.AddLocation(new Location("a"));
//Verify that mockLocationMap.Add(..) is not called
}
How would you go about writing Unit Test in this style in DotNet? Or you don't take this path for the known constraints?
Your help is much appreciated.
Another way is to use a unit testing tool that allows you to mock concrete classes, for instance i'm using Typemock Isolator and with it was able to create the test that you wanted to make:
[TestMethod]
public void TestMethod1()
{
var fakeLocationMap = Isolate.Fake.Instance<SortedDictionary<string, Location>>();
Isolate.WhenCalled(() => fakeLocationMap.ContainsKey(string.Empty)).WillReturn(true);
var instance = new LocationMapper(fakeLocationMap);
var res = instance.AddLocation(new Location("a"));
Isolate.Verify.WasNotCalled(() => fakeLocationMap.Add(string.Empty, null));
}
You should not mock dictionary here. Actually it's an implementation detail of LocationMapper class. And it should be hidden via encapsulation. You might use anything else to store locations - array, list or simple dictionary. It doesn't matter if LocationMapper meets its requirements. What are requirements in this case? Something like
Location mapper should be able to map location which was added to mapper
Currently your mapper is pretty useless and it adds nothing to dictionary behavior. You missing the core - mapping. I can only assume how this class is going to be used. You need some public interface for mapping. And test should look like (AutoFixture and FluentAssertions used here):
var mapper = new LocationMapper();
var location = fixture.Create<Location>();
mapper.AddLocation(location);
mapper.Map(location.Name).Should().Be(location);
While this test is passing you can add locations to mapper and use mapper to map those locations.
You have two options: If you use VS Enterprise, use Microsoft Fakes to generate a Shim for your class. (ping me if you want a sample)>
If you don't use VS Enterprise (as the majority of people here) you will have to resort to reflection:
[Test]
public void AddLocation_ShouldNotAddLocationAgainWhenAlreadyPresent()
{
var locationMapper = new LocationMapper(mockLocationMap);
locationMapper.AddLocation(new Location("a"));
var dict = ((SortedDictionary<string, Location>)typeof(LocationMapper).GetField("locationMap", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(locationMapper));
Assert.AreEqual("a", dict.FirstOrDefault().Name)
}
Related
In below code i am using Moq to write a sample test. I have created a Mock Object and I am using SetupProperty to setup fake value to be returned for the property. But i get above error at line _sharedService.VerifyAll().
I know i am missing something trivial, but not exactly sure what. Could anyone please help?
[TestFixture]
public class ObjectFactoryTests : TestFixtureBase
{
private Mock<ISharedService> _sharedService;
[SetUp]
public void SetUp()
{
_sharedService = new Mock<ISharedService>(MockBehavior.Strict);
}
protected override void VerifyAll()
{
_sharedService.VerifyAll();
}
private IObjectFactory GetObjectFactory()
{
return new ObjectFactory(sharedService.Object);
}
[Test]
public void ObjectFactory_GenerateObject_Request_Success()
{
MyObject1 request = something;
var requestData = new Dictionary<string, object>();
requestData.TryAdd(Cache.Client, Constants.CLIENT);
_sharedService.SetupProperty(m => m.RequestData, requestData);
var factory = GetObjectFactory();
var actual = factory.GenerateObject(request);
Assert.That(actual.Client, Is.EqualTo(requestData[Cache.Client].ToString()), Constants.CLIENT);
VerifyAll();
}
}
public class ObjectFactory : IObjectFactory
{
ISharedService SharedService = something;
public MyObject GenerateObject(MyObject1 request)
{
MyObject obj = new MyObject(request);
obj.Client = SharedService.RequestData[Cache.Client].ToString();
return obj;
}
}
If I understood correctly, you try to setup property expectations.
Try following instead of _sharedService.SetupProperty(m => m.RequestData, requestData);:
_sharedService.Setup(foo => foo.RequestData).Returns(requestData);
You can read more information in Moq documentation
For a get-set peoperty, SetupProperty will create two setups: one for the getter, and one for the setter. Since you're only reading the property, that leaves the property for the setter unmatched, therefore the error.
To avoid this, use mock.SetupGet(m => m.Property).Returns(() => value) to only create a setup for the getter.
Btw.: SetupProperty actually has a different purpose than what you might think: It shouldn't be used to set up an expectation; instead, it is used to "stub" a property such that it retains the value it's been set to last. The fact that Verify[All] even includes such stubbed properties in its checks is probably an error (which has already been fixed in SetupAllProperties).
I'm using MoQ in C# to do some Unit tests/BDD tests, and I've often the need of generating the same object twice(because it will be potentially used in dictionary). Or something 99% the same but just with a different ID.
Is there a way to "clone" the Mock definition? Or to generate two objects with the same definition?
You should create a helper method that constructs that takes in some parameters to construct the Mock object.
[Test]
public void MyTest()
{
Mock<ITestObject> myMock = CreateObject(1);
ITestObject obj = myMock.Object;
}
private Mock<ITestObject> CreateObject(int id)
{
Mock<ITestObject> mock = new Mock<ITestObject>();
mock.SetupGet(o => o.ID).Returns(id);
return mock;
}
private interface ITestObject
{
int ID { get; set; }
}
If you just need a collection of data to unit test with, you may consider something like AutoFixture as well. It can work with Moq in the case of classes you want to mock. You teach AutoFixture how to create YourClass, and you can even set rules like "my IDs should be strings with capital letters and no more than X amount of them."
Then you'd just use autofixture.
var fixture = new Fixture();
var tetsClasses = fixture.CreateMany<TestClass>();
This is really just to give you an idea. You can do quite a but more with it, and it plays really well with Moq.
An alternative is to use a data builder pattern to create your data. So you could start with something simple and just keep adding onto it as you find new edge cases on how you need to build the data. Just build a fluent API on it and build the data however you want.
internal class TestClassBuilder<T> : where T : TestClass
{
int Id {get; set;}
public T WithId(int id)
{
this.Id = id;
return this;
}
public virtual T Build()
{
return new T()
{
if(this.Id)
Id = this.Id; // if you chose to set it, then assign it
else
Id = GetRandomId() // you can figure a solution here
}
}
}
Then call it like:
var stubOne = TestClassBuilder.WithId(1).Build();
You can extend it to build a list if you want.
I like fluent APIs on data builders, because you can start to tell your story with the methods you create, and it keeps your Arrange section neat and tidy.
Example:
var UnderAgeCustomer = new CustomerBuilder
.UnderAge
.WithFakeId
.InACrowd
.LooksYoung
.Build()
You could even add on
public static implicit operator T(TestClassBuilder<T> builder)
{
return builder.Build();
}
And you wouldn't need to use the .Build() part all the time (I think build adds unnecessary noise). Just don't try assigning that to a var, it won't work.
TestClass MockTwo = TestClassBuilder.WithId(2);
I would say you could also use a fixture pattern to track of all this ... but between that and the databuilder, you may as well use AutoFixture and Moq as I suggested :)
The problem
I have a pretty big application that makes use of a bunch of other services.
For testing scenarios I don't want my unit tests to rely on third party systems, so I want to replace the services with fakes or mocks, or whatever.
I've already done most of the hard labor, and replaced the concrete services with a IService. The concrete Service is wired in with a DI framework
Now I want to replace those with random generated fakes.
The code
Interface of example service:
public interface ISimpleService
{
int Fizz(int input);
string Buzz(string input);
}
Interface of example service factory:
public interface ISimpleServiceFactory
{
ISimpleService Create();
}
Implementation simple as possible
public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var service = fixture.Create<ISimpleService>();
var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}
This shows what I basically want. I just want autofixture to create some dynamic proxy object for me, with methods that return something random of the type specified in the interface...
Note that I've used AutoMoq here, because by default Fixture doesnt want to create objects from interfaces, but I've tried other frameworks too: FakeItEasy, AutoRhinoMock
Workaround
Implementation that kind of works by manually setting everything
public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var serviceMock = fixture.Create<Mock<ISimpleService>>();
// These two lines below cause the magic now
serviceMock.Setup(x => x.Fizz(It.IsAny<int>())).Returns(fixture.Create<int>());
serviceMock.Setup(x => x.Buzz(It.IsAny<string>())).Returns(fixture.Create<string>());
var service = serviceMock.Object;
var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}
This does give me the desired result: fizzResult with a random int, buzzResult with a random string (a guid by default)
However, this is only a small example, my actual service references are a lot bigger, with up to 100s of methods... (they are external soap services etc, can't help it)
I don't want to set up everything manually, if theres a generic solution, that would be great...
An implementation for factories that kind of works by manually setting everything
So, as you might have noticed, I've also posted a ISimpleServiceFactory interface. This resembles the actual situation, since the actual concrete ISimpleService requires a bunch of configuration.
So, if we'd use the kind of working solution, we'd come to this:
public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var serviceFactoryMock = fixture.Create<Mock<ISimpleServiceFactory>>();
var serviceMockDelegate = new Func<ISimpleService>(() =>
{
var serviceMock = fixture.Create<Mock<ISimpleService>>();
serviceMock.Setup(x => x.Fizz(It.IsAny<int>())).Returns(fixture.Create<int>());
serviceMock.Setup(x => x.Buzz(It.IsAny<string>())).Returns(fixture.Create<string>());
return serviceMock.Object;
});
serviceFactoryMock.Setup(x => x.Create()).Returns(serviceMockDelegate);
var service = serviceFactoryMock.Object.Create();
var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}
This seems to be getting a bit of a mess, and this is a pretty small interface.
The actual services are many levels deep, with 100s of methods.
For methods in my code that require specific conditions I'll obviously still manually set those conditions, but everything else should be random values by default. Generating large amounts of random objects allows for a bit of fuzzy testing too
Is there a way to automatically generate random objects without all this manual setting up?
You don't need a factory nor do you need to setup every method within your interfaces, if I understand correctly you simply want to use Fixture to create a proxy which returns random values for every method you invoke on that proxy. Instead of using AutoMoqCustomization use AutoConfiguredMoqCustomization. It's all in the nuget package called Fixture.AutoMoq.
class Program
{
static void Main(string[] args)
{
}
}
[TestFixture]
public class program
{
[Test]
public void some_test()
{
var fixture = new Fixture();
fixture.Customize(new AutoConfiguredMoqCustomization());
var simpleServices = fixture.CreateMany<ISimpleService>();
foreach (var simpleService in simpleServices)
{
string randomString = simpleService.Buzz("hello");
int randomInt = simpleService.Fizz(15);
}
}
}
public interface ISimpleService
{
int Fizz(int input);
string Buzz(string input);
}
I'm working on an app with a domain model similar to this, where a LineItem can be referenced both from an Order as well as from a Shipment.
If I'm using AutoFixture to generate an Order, how can I use the same set of LineItems for both order.LineItems and order.Shipments*.ItemShipments*.LineItem?
Theoretically, the following test ought to pass:
var fullyShippedOrder = fixture.CreateAnonymous<Order>();
var shippedLineItems = fullyShippedOrder.Shipments
.SelectMany(o => o.ItemShipment, (s, i) => i.LineItem)
.Distinct();
Assert.EqualCollection(fullyShippedOrder.LineItems, shippedLineItems);
... although I would also want to be able to generate partially-shipped orders depending on the test.
(There's a solid argument to be made that a line item on an Order and a line item on a Shipment are different things and I shouldn't be using the same class to represent them. However, the data I'm working with comes from a legacy system and there isn't much that can be done about it. )
As you said, the friction you're experiencing in your tests is most likely a sign of a design problem in the domain model. Ideally, you should listen to your tests and fix the problem at its root. However, granted that it isn't feasible in this case, here's a workaround.
You can configure the Fixture to always return LineItem objects out of a fixed sequence by using the Register<T>(Func<T> creator) method.
Here's an example packaged up in a customization:
public class GenerateLineItemFromFixedSequence : ICustomization
{
public void Customize(IFixture fixture)
{
var items = CreateFixedLineItemSequence(fixture);
fixture.Register(() => GetRandomElementInSequence(items));
}
private static IEnumerable<LineItem> CreateFixedLineItemSequence(IFixture fixture)
{
return fixture.CreateAnonymous<LineItem[]>();
}
private static LineItem GetRandomElementInSequence(IEnumerable<LineItem> items)
{
var randomIndex = new Random().Next(0, items.Count());
return items.ElementAt(randomIndex);
}
}
In order to apply this behavior in the context of a test, just add the customization to the Fixture object:
fixture.Customize(new GenerateLineItemFromFixedSequence());
Similarly, you could create other customizations that generate the fixed sequence of LineItem objects in different states, like the partially-shipped orders you mentioned, and use them in different tests.
An observation
It's interesting to note that this customization can be made generic, since the algorithm itself isn't coupled with the type of objects being created. This would effectively transform it into a strategy.
So, modifying the customization by introducing a generic parameter:
public class GenerateFromFixedSequence<T> : ICustomization
{
public void Customize(IFixture fixture)
{
var items = CreateFixedSequence(fixture);
fixture.Register(() => GetRandomElementInSequence(items));
}
private static IEnumerable<T> CreateFixedSequence(IFixture fixture)
{
return fixture.CreateAnonymous<T[]>();
}
private static T GetRandomElementInSequence(IEnumerable<T> items)
{
var randomIndex = new Random().Next(0, items.Count());
return items.ElementAt(randomIndex);
}
}
would allow you to use it for different objects:
fixture.Customize(new GenerateFromFixedSequence<LineItem>());
fixture.Customize(new GenerateFromFixedSequence<Order>());
fixture.Customize(new GenerateFromFixedSequence<Shipment>());
I'm new to mocking/testing and wanting to know what level should you go to when testing. For example in my code I have the following object:
public class RuleViolation
{
public string ErrorMessage { get; private set; }
public string PropertyName { get; private set; }
public RuleViolation( string errorMessage )
{
ErrorMessage = errorMessage;
}
public RuleViolation( string errorMessage, string propertyName )
{
ErrorMessage = errorMessage;
PropertyName = propertyName;
}
}
This is a relatively simple object. So my question is:
Does it need a unit test?
If it does what do I test and how?
Thanks
it doesn't contain any logic => nothing to test
I would say probably not. The only thing that you would probably want to verify if it is extremely important are the access modifiers:
public string ErrorMessage { get; private set; }
public string PropertyName { get; private set; }
If it is really really important that code outside the class cannot modify them that might be the only thing I would try and verify.
Here is how you can get the accessors in a property:
class Program
{
static void Main(string[] args)
{
var property = typeof(Test).GetProperty("Accessor");
var methods = property.GetAccessors();
}
}
public class Test
{
public string Accessor
{
get;
private set;
}
}
With the property.GetAccessors();
You can see if the setter is there. If it is, then the setter is public. (There is also properties IsPrivate and IsPublic you can use to verify the other Accessors as well).
If it were my code and my object I would have tests for it, no matter how simple or complicated the class is, period. Even if the class seems unlikely to break, tests are where, IMO, you document your assumptions, design decisions, and proper usage.
By doing so, you not only validate that what you have works as intended, but you have the opportunity to think through typical scenarios (what happens if the ctor params are null or empty or have white space at the end? Why is the PropertyName optional in an immutable class?).
And IF (when?) requirements change you have a solid starting point for addressing that. And IF this trivial class somehow doesn't interact nicely with all of the other classes, you may have a test to catch that before your customers do.
It's just the right way to engineer your code.
HTH,
Berryl
You could unit test this object, but it's so simple as to not require it. The test would be something like (NUnit example)
[Test]
public void TestRuleViolationConstructorWithErrorMessageParameterSetsErrorMessageProperty() {
// Arrange
var errorMessage = "An error message";
// Act
var ruleViolation = new RuleViolation(errorMessage);
// Assert
Assert.AreEqual(errorMessage, ruleViolation.ErrorMessage);
}
There's little value to writing tests like these, however, as you are testing that the .NET framework's properties work correctly. Generally you can trust Microsoft to have got this right :-)
Regarding mocking, this is useful when your class under test has a dependency, perhaps on another class in your own application, or on a type from a framework. Mocking frameworks allow you call methods and properties on the dependecy without going to the trouble of building the dependency concretely in code, and instead allow you to inject defined values for properties, return values for methods, etc. Moq is an excellent framework, and a test for a basic class with dependency would look something like this:
[Test]
public void TestCalculateReturnsBasicRateTaxForMiddleIncome() {
// Arrange
// TaxPolicy is a dependency that we need to manipulate.
var policy = new Mock<TaxPolicy>();
bar.Setup(x => x.BasicRate.Returns(0.22d));
var taxCalculator = new TaxCalculator();
// Act
// Calculate takes a TaxPolicy and an annual income.
var result = taxCalculator.Calculate(policy.Object, 25000);
// Assert
// Basic Rate tax is 22%, which is 5500 of 25000.
Assert.AreEqual(5500, result);
}
TaxPolicy would be unit tested in its own fixture to verify that it behaves correctly. Here, we want to test that the TaxCalculator works correctly, and so we mock the TaxPolicy object to make our tests simpler; in so doing, we can specify the behaviour of just the bits of TaxPolicy in which we're interested. Without it, we would need to create hand-rolled mocks/stubs/fakes, or create real instances of TaxPolicy to pass around.
There's waaaaay more to Moq than this, however; check out the quick-start tutorial to see more of what it can do.
Even if simple, there's logic in your constructors. I would test that:
RuleViolation ruleViolation = new RuleViolation("This is the error message");
Assert.AreEqual("This is the error message", ruleViolation.ErrorMessage);
Assert.IsEmpty(ruleViolation.PropertyName);
RuleViolation ruleViolation = new RuleViolation("This is the error message", "ThisIsMyProperty");
Assert.AreEqual("This is the error message", ruleViolation.ErrorMessage);
Assert.AreEqual("ThisIsMyProperty", ruleViolation.PropertyName);