Mocking Registry and File System - c#

If I am to write unit tests for reading/writing/creating registry entries or files, my understanding is that I should not be using real registry and file system but should mock them in a light weight manner.
What mocking framework would you recommend for mocking these in C# desktop/WPF style apps?
What would be a good introductory reading into this topic?

OK, here's an example.
Given these classes:
public interface IRegistryActions
{
bool WriteValue(string key, string value);
}
public class RegistryActions : IRegistryActions
{
public bool WriteValue(string key, string value)
{
// pseudocode
// var key = Registry.OpenKey(key);
// Registry.WriteValue(key, value);
}
}
And this class that uses them: the class which will perform the actions is passed to the constructor in this example, but could as easily be a property. This means that whenever you want to actually use the class in your actual code, you can explicitly pass a class that implements IRegistryActions as a parameter - e.g. var exampleClass = new ExampleClass(new RegistryActions()); - or alternatively default to the actual implementation if passed null, i.e. this.registryActions = registryActions ?? new RegistryActions();
public class ExampleClass
{
private IRegistryActions registryActions;
public ExampleClass(IRegistryActions registryActions)
{
this.registryActions = registryActions;
}
public bool WriteValue(string key, string value)
{
return registryActions.WriteValue(key, value);
}
}
So in your unit test you want to verify that the call is made with the right parameters. How exactly you do this depends on what mocking framework you use, which is generally either a matter of personal choice or you use what's already used.
[Test]
public void Test_Registry_Writes_Correct_Values()
{
string key = "foo";
string value = "bar";
// you would normally do this next bit in the Setup method or test class constructor rather than in the test itself
Mock<IRegistryActions> mock = MockFramework.CreateMock<IRegistryActions>();
var classToTest = new ExampleClass(mock); // some frameworks make you pass mock.Object
// Tell the mock what you expect to happen to it
mock.Expect(m => m.WriteValue(key, value));
// Call the action:
classToTest.WriteValue(key, value);
// Check the mock to make sure it happened:
mock.VerifyAll();
}
In this you're asserting that your class has called the correct method on the interface, and passed the correct values.

Related

Is there a good way to unit test using Environment Variables?

I have a couple of environment variables that are used as part of creating defaults for config options. Basically if the config options property in question is null then use the value from the specified environment variable.
I want to test the options objects correctly use the environment variable when null, so initially thought I'd just set the specified environment variable. However, this is an environment variable that will actually be used on the environment and therefore I don't really want to be messing with it. Is there a way I can wrap environment variables using an interface or something so I can mock the SetEnironmentVariable() method or something similar?
In terms of code my options objects look something like this:
public sealed record MyOptions
{
public string SomeProperty { get; set; }
public MyOptions()
{
var defaultVal = Environment.GetEnvironmentVariable("MY_VARIABLE");
SomeProperty = SomeProperty ?? defaultVal;
}
}
So if the SomeProperty hasn't been set via config, it will use the default value from the specified environment variable. I was thinking perhaps an EnvironmentVariableService, that retrieves all environment variables and puts them in a ConcurrentDictionary, and that's used in the place of the Environment.
Your question contains the answer🙂.
It is quite normal to wrap common .NET concrete implementations such as a timer, DateTime.Now, and utility class such as Environment and then inject that wrapper into the places that would normally use the concrete implementation.
Your case is a little unique in that you need access inside a sealed record. I would recommend you create a singleton of the service in that case. Ideally you avoid this approach.
The wrapper acts as an abstraction as mentioned in the comments to your question, and allows for the implementation to be swapped out in circumstances such as unit tests.
I happen to have implemented such a thing as I had this need as well. Here's the code.
public interface IEnvironmentService
{
string? GetEnvironmentVariable(string name);
void SetEnvironmentVariable(string name, string? value);
}
public class MockEnvironmentService : IEnvironmentService
{
public string? GetEnvironmentVariable(string name)
{
var found = !_dictionary.TryGetValue(name, out var value);
if (!found) value = null;
_actions.Add(new GetAction(name, value, found));
return value;
}
public void SetEnvironmentVariable(string name, string? value)
{
_dictionary[name] = value;
_actions.Add(new SetAction(name, value));
}
public IReadOnlyCollection<Action> AllActions => _actions.ToArray();
public IReadOnlyCollection<GetAction> GetActions => _actions.OfType<GetAction>().ToArray();
public IReadOnlyCollection<SetAction> SetActions => _actions.OfType<SetAction>().ToArray();
// see note after the code
private readonly Dictionary<string, string?> _dictionary = new(StringComparer.InvariantCultureIgnoreCase);
private readonly List<Action> _actions = new();
}
public class EnvironmentVariableService : IEnvironmentService
{
public string? GetEnvironmentVariable(string name) => Environment.GetEnvironmentVariable(name);
public void SetEnvironmentVariable(string name, string? value) => Environment.SetEnvironmentVariable(name, value);
}
public record Action(string Name, string? Value);
public record SetAction(string Name, string? Value) : Action(Name, Value);
public record GetAction(string Name, string? Value, bool WasFound) : Action(Name, Value);
At the beginning of your tests, if you need to preset/seed some environment variables to test read-side code, you can call MockEnvironmentService.SetEnvironmentVariable().
The implementation above uses a case insensitive dictionary for the keys, but whether names are case sensitive really depends on the OS.
Finally, the mock records the get/set calls in the order they occur, and you can use the properties in your assertions.

Moq.MockException: The following setups on mock were not matched

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

Generate two object of the same mock

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

Can AutoFixture execute a delegate at object creation time?

I'm looking to customize the creation-time behavior of AutoFixture such that I can set up some dependent objects after the properties of the fixture have been generated and assigned.
For example, suppose I have a method that customizes a User because its IsDeleted property always has to be false for a certain set of tests:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsDeleted { get; set; }
}
public static ObjectBuilder<User> BuildUser(this Fixture f)
{
return f.Build<User>().With(u => u.IsDeleted, false);
}
(I hand an ObjectBuilder back to the test so it can further customize the fixture if necessary.)
What I'd like to do is automatically associate that user with an anonymous collection by its Id at creation time, but I can't do this as-is because Id has not been generated by the time I hand the return value back to the unit test proper. Here's the sort of thing I'm trying to do:
public static ObjectBuilder<User> BuildUserIn(this Fixture f, UserCollection uc)
{
return f.Build<User>()
.With(u => u.IsDeleted, false);
.AfterCreation(u =>
{
var relation = f.Build<UserCollectionMembership>()
.With(ucm => ucm.UserCollectionId, uc.Id)
.With(ucm => ucm.UserId, u.Id)
.CreateAnonymous();
Repository.Install(relation);
}
}
Is something like this possible? Or perhaps there is a better way to accomplish my goal of creating an anonymous object graph?
For the Build method, this isn't possible, and probably never will be, because there are much better options available.
First of all, it should never be necessary to write static helper methods around the Build method. The Build method is for truly one-off initializations where one needs to define property or field values before the fact.
I.e. imagine a class like this:
public class MyClass
{
private string txt;
public string SomeWeirdText
{
get { return this.txt; }
set
{
if (value != "bar")
throw new ArgumentException();
this.txt = value;
}
}
}
In this (contrived) example, a straight fixture.CreateAnonymous<MyClass> is going to throw because it's going to attempt to assign something other than "bar" to the property.
In a one-off scenario, one can use the Build method to escape this problem. One example is simply to set the value explicitly to "bar":
var mc =
fixture.Build<MyClass>().With(x => x.SomeWeirdText, "bar").CreateAnonymous();
However, even easier would be to just omit that property:
var mc =
fixture.Build<MyClass>().Without(x => x.SomeWeirdText).CreateAnonymous();
However, once you start wanting to do this repeatedly, there are better options. AutoFixture has a very sophisticated and customizable engine for defining how things get created.
As a start, one could start by moving the omission of the property into a customization, like this:
fixture.Customize<MyClass>(c => c.Without(x => x.SomeWeirdText));
Now, whenever the fixture creates an instance of MyClass, it's just going to skip that property altogether. You can still assign a value afterwards:
var mc = fixture.CreateAnonymous<MyClass>();
my.SomeWeirdText = "bar";
If you want something more sophisticated, you can implement a custom ISpecimenBuilder. If you want to run some custom code after the instance has been created, you can decorate your own ISpecimenBuilder with a Postprocessor and supply a delegate. That might look something like this:
fixture.Customizations.Add(
new Postprocessor(yourCustomSpecimenBuilder, obj =>
{ */ do something to obj here */ }));
(BTW, are you still on AutoFixture 1.0? IIRC, there hasn't been an ObjectBuilder<T> around since then...)
There's a useful discussion on this topic on the AutoFixture CodePlex site.
I believe my postprocessor Customization linked over there should help you. Example usage:
class AutoControllerDataAttribute : AutoDataAttribute
{
public AutoControllerDataAttribute()
: this( new Fixture() )
{
}
public AutoControllerDataAttribute( IFixture fixture )
: base( fixture )
{
fixture.Customize( new AutoMoqCustomization() );
fixture.Customize( new ApplyControllerContextCustomization() );
}
class ApplyControllerContextCustomization : PostProcessWhereIsACustomization<Controller>
{
public ApplyControllerContextCustomization()
: base( PostProcess )
{
}
static void PostProcess( Controller controller )
{
controller.FakeControllerContext();
// etc. - add stuff you want to happen after the instance has been created

Confused about this unit test!

So basically, I have an abstract class which has a unique, incremental ID - Primitive. When a Primitive (or more precisely, an inheritor of Primitive) is instantiated, the ID is incremented - up to the point where the ID overflows - at which point, I add a message to the exception and rethrow.
OK, that all works fine... but I'm trying to test this functionality and I've never used mocking before. I just need to make enough Primitives for the ID to overflow and assert that it throws at the right time.
It is unreasonable to instantiate 2 billion objects to do this! However I don't see another way.
I don't know if I'm using mocking correctly? (I'm using Moq.)
Here's my test (xUnit):
[Fact(DisplayName = "Test Primitive count limit")]
public void TestPrimitiveCountLimit()
{
Assert.Throws(typeof(OverflowException), delegate()
{
for (; ; )
{
var mock = new Mock<Primitive>();
}
});
}
and:
public abstract class Primitive
{
internal int Id { get; private set; }
private static int? _previousId;
protected Primitive()
{
try
{
_previousId = Id = checked (++_previousId) ?? 0;
}
catch (OverflowException ex)
{
throw new OverflowException("Cannot instantiate more than (int.MaxValue) unique primitives.", ex);
}
}
}
I assume I'm doing it wrong - so how do I test this properly?
You don't need mocking for this. You use mocking when two classes work together and you want to replace one class with a mock (fake) one so you only have to test the other one. This is not the case in your example.
There is however a way you could use mocks, and that fixes your issue with the 2bln instances. If you separate the ID generation from the Primitive class and use a generator, you can mock the generator. An example:
I've changed Primitive to use a provided generator. In this case it's set to a static variable, and there are better ways, but as an example:
public abstract class Primitive
{
internal static IPrimitiveIDGenerator Generator;
protected Primitive()
{
Id = Generator.GetNext();
}
internal int Id { get; private set; }
}
public interface IPrimitiveIDGenerator
{
int GetNext();
}
public class PrimitiveIDGenerator : IPrimitiveIDGenerator
{
private int? _previousId;
public int GetNext()
{
try
{
_previousId = checked(++_previousId) ?? 0;
return _previousId.Value;
}
catch (OverflowException ex)
{
throw new OverflowException("Cannot instantiate more than (int.MaxValue) unique primitives.", ex);
}
}
}
Then, your test case becomes:
[Fact(DisplayName = "Test Primitive count limit")]
public void TestPrimitiveCountLimit()
{
Assert.Throws(typeof(OverflowException), delegate()
{
var generator = new PrimitiveIDGenerator();
for (; ; )
{
generator.GetNext();
}
});
}
This will run a lot faster and now you're only testing whether the ID generator works.
Now, when you e.g. want to test that creating a new primitive actually asks for the ID, you could try the following:
public void Does_primitive_ask_for_an_ID()
{
var generator = new Mock<IPrimitiveIDGenerator>();
// Set the expectations on the mock so that it checks that
// GetNext is called. How depends on what mock framework you're using.
Primitive.Generator = generator;
new ChildOfPrimitive();
}
Now you have separated the different concerns and can test them separately.
The point of the mock is to simulate an external resource. It's not what you want, you want to test your object, no mock needed in this szenario. Just instantiate the 2 billion objects if you like to, it doesn't hurt since the GC will throw away the old instances (but may take a while to complete).
Id' actually add another constructor which accepts a strarting value for the identity counter, so that you can actually start close to int.MaxValue and therefore don't need to instatiate as many objects.
Also, just from readin the source I can tell that your object will fail the test. ;-)
You have two problems baked into this question:
How to unit test an abstract class, that you can't instantiate.
How to efficiently unit test functionality that requires two billion instances to be created and destroyed.
I think the solutions are pretty simple, even though you'll have to re-think the structure of your object slightly.
For the first problem, the solution is as simple as adding a fake that inherits Primitive, but adds no functionality, to your test project. You can then instantiate your fake class instead, and you'll still be testing the functionality of Primitive.
public class Fake : Primitive { }
// and in your test...
Assert.Throws(typeof(OverflowException), delegate() { var f = new Fake(int.MaxValue); });
For the second problem, I'd add a constructor that takes an int for the previous ID, and use constructor chaining to "not need it" in your actual code. (But how to you get to know of the previous id otherwise? Can't you set that to int.MaxValue-1 in the setup of your test?) Think of it as dependecy injection, but you're not injecting anything complex; you're just injecting a simple int. It could be something along these lines:
public abstract class Primitive
{
internal int Id { get; private set; }
private static int? _previousId;
protected Primitive() : Primitive([some way you get your previous id now...])
protected Primitive(int previousId)
{
_previousId = previousId;
try
{
_previousId = Id = checked (++_previousId) ?? 0;
}
catch (OverflowException ex)
{
throw new OverflowException("Cannot instantiate more than (int.MaxValue) unique primitives.", ex);
}
}
All has been said in the other answers. I just want to show you an alternative, maybe this is somehow interesting for you.
If you made the _previousId field of your Primitive class internal (and included the respective InternalsVisibleTo attribute, of course), then your test could be as simple as this with the Typemock Isolator tool:
[Fact(DisplayName = "Test Primitive count limit"), Isolated]
public void TestPrimitiveCountLimit()
{
Primitive._previousId = int.MaxValue;
Assert.Throws<OverflowException>(() =>
Isolate.Fake.Instance<Primitive>(Members.CallOriginal, ConstructorWillBe.Called));
}
Sure, Typemock comes with some license costs, but it definitely makes life much easier and saves you a lot of time, if you have to write large amounts of test code - especially on systems which are not easily tested or are even impossible to test with a free mocking framework.
Thomas

Categories