How to unit test immutable class constructors? - c#

I have an immutable class with some private fields that are set during the constructor execution. I want to unit test this constructor but I'm not sure the "best practice" in this case.
Simple Example
This class is defined in Assembly1:
public class Class2Test
{
private readonly string _StringProperty;
public Class2Test()
{
_StringProperty = ConfigurationManager.AppSettings["stringProperty"];
}
}
This class is defined in Assembly2:
[TestClass]
public class TestClass
{
[TestMethod]
public void Class2Test_Default_Constructor()
{
Class2Test x = new Class2Test();
//what do I assert to validate that the field was set properly?
}
}
EDIT 1: I have answered this question with a potential solution but I'm not sure if it's the "right way to go". So if you think you have a better idea please post it.
This example isn't really worth testing, but assume the constructor has some more complex logic. Is the best approach to avoid testing the constructor and to just assume it works if all the tests for the methods on the class work?
EDIT 2: Looks like I made the sample a little to simple. I have updated it with a more reasonable situation.

Nothing, unless you are using that field. You don't want over-specification via tests. In other words, there is no need to test that the assignment operator works.
If you are using that field in a method or something, call that method and assert on that.
Edit:
assume the constructor has some more complex logic
You shouldn't be performing any logic in constructors.
Edit 2:
public Class2Test()
{
_StringProperty = ConfigurationManager.AppSettings["stringProperty"];
}
Don't do that! =) Your simple unit test has now become an integration test because it depends on the successful operation of more than one class. Write a class that handles configuration values. WebConfigSettingsReader could be the name, and it should encapsulate the ConfigurationManager.AppSettings call. Pass an instance of that SettingsReader class into the constructor of Class2Test. Then, in your unit test, you can mock your WebConfigSettingsReader and stub out a response to any calls you might make to it.

I have properly enabled [InternalsVisibleTo] on Assembly1 (code) so that there is a trust relationship with Assembly2 (tests).
public class Class2Test
{
private readonly string _StringProperty;
internal string StringProperty { get { return _StringProperty; } }
public Class2Test(string stringProperty)
{
_StringProperty = stringProperty;
}
}
Which allows me to assert this:
Assert.AreEqual(x.StringProperty, "something");
The only thing I don't really like about this is that it's not clear (without a comment) when you are just looking at Class2Test what the purpose of the internal property is.
Additional thoughts would be greatly appreciated.

In your edit, you now have a dependancy on ConfigurationManager that is hard to test.
One suggestion is to extract an interface to it and then make the Class2Test ctor take an IConfigManager instance as a parameter. Now you can use a fake/mock object to set up its state, such that any methods that rely on Configuration can be tested to see if they utilize the correct values...
public interface IConfigManager
{
string FooSetting { get; set; }
}
public class Class2Test
{
private IConfigManager _config;
public Class2Test(IConfigManager configManager)
{
_config = configManager;
}
public void methodToTest()
{
//do something important with ConfigManager.FooSetting
var important = _config.FooSetting;
return important;
}
}
[TestClass]
public class When_doing_something_important
{
[TestMethod]
public void Should_use_configuration_values()
{
IConfigManager fake = new FakeConfigurationManager();
//setup state
fake.FooSetting = "foo";
var sut = new Class2Test(fake);
Assert.AreEqual("foo", sut.methodToTest());
}
}

Related

Set up Private variable in Class for Nunit Test

I'm trying to write a unit test for a class but the class has a Private variable initiated when the class is created..
public class OrderFormService : IOrderFormService
{
private readonly IOrderItems _orderItems;
private readonly string _orderStartingGroup;
// constructor
public OrderFormService(IOrderItems orderItems)
{
_orderItems = orderItems;
_orderStartingGroup = "Sales";
{
// Other Methods
}
I'm trying to write a unit test now and to test a method in this class and it utilises the variable _orderStartingGroup...
[TestFixture]
public class OrderFormServiceTests
{
private ITreatmentFormService _service;
private Mock<IOrderItems> _orderItems;
[SetUp]
public void SetUp()
{
_orderItems = new Mock<IOrderItems>();
_service = new OrderFormService(_orderItems);
}
}
Is it possible to set up the _orderStartingGroup in OrderFormServiceTest so it can be used in unit tests for testing some methods in OrderFormService? If so, how do I go about it? I've tried googling it but results keep talking about accessing private variables in the class you're testing but this isn't what I'm trying to do.
Thanks in advance :)
Well even if there is a way of setting private field directly from unit test method it’ll break an architectural principle or two..
There are a few ways of how to deal with this problem. The simplest solution would be to change the ctor signature by adding an optional parameter:
// constructor
public OrderFormService(IOrderItems orderItems, string orderStartingGroup = null)
{
_orderItems = orderItems;
_orderStartingGroup = orderStartingGroup ?? "Sales";
{
And use it in unit test:
[SetUp]
public void SetUp()
{
_orderItems = new Mock<IOrderItems>();
_service = new OrderFormService(_orderItems, “testValue”);
}
I think this might an indicator that you are doing something wrong. I would rather focus on public interfaces rather than testing internal implementation. If this somehow reflected in public interface there should be a way to set it via public interface or convention (say read from a config file).
But if you absolutely need to do that, you can consider following:
Use fabjan's answer
Set private field value with reflection
Make this private member as protected and create an derived test class.

How do I unit test a class that relies on HttpContext.GetGlobalResourceObject?

I'm trying to add tests to a webforms project. There's a static method to grab lines from resource files. One of the classes I'm trying to test, relies on grabbing text from the resource file.
public static class MyStaticClass {
public static string getText(String name)
{
String s = HttpContext.GetGlobalResourceObject("MyResources", name).ToString();
return s;
}
}
public class ClassUnderTest
{
// returns: "Hey it's my text"
private string _eg = MyStaticClass.getText("label_in_resources.resx_file")
}
class UnitTests
{
[Test]
public void TestMyClass()
{
ClassUnderTest _cut = new ClassUnderTest();
// errors out because ClassUnderTest utilizes getText
// which requires HttpContext.GetGlobalResourceObject
// ... other stuff
}
}
Note: these are simplistic examples.
The issue is that I get a Test Failed with the message:
Message: System.NullReferenceException : Object reference not set to an instance of an object.
With my sleuthing, I've determined that this is because HttpContext is null during these tests.
I've looked at quite a few SO posts on mocking HttpContext but I don't think that I fully understand what exactly they're doing as they're typically dealing with MVC and not Webforms. Still most of them use HttpContextBase and/or HttpContextWrapper but again, I'm not sure how to implement them.
Also - I'm not directly testing the getText method. I know it works. I'm testing a class that uses it. Will mocking the HttpContext even help in this situation?
I do realize that this is sort of a hybrid of a unit test / integration test, so if this isn't the best way, I'm all ears... or.. eyes rather.
Edit
For now, I modified my getText method to return the key (name) if the result of HttpContext.GetGlobalResourceObject is null. Then I updated my tests to expect the key instead of the value. It's not ideal, but it works and allows me to continue. If there's a better way, please let me know.
public static class MyStaticClass {
public static string getText(String name)
{
String s = HttpContext.GetGlobalResourceObject("MyResources", name);
return s != null ? s.ToString() : name;
}
}
Original answer with Fakes (see below for dealing with removing static)
So there's one caveat that I completely forgot about until I just tried to do this. I am pretty sure Fakes still requires Enterprise version of VS. I don't know if there's a way to get it to work with NUnit, but when you aren't able to change the code sometimes you have to just deal with it.
Here's an example of Shimming your static method. You don't need to worry about HttpContext (yet) since you aren't using it directly. Instead you can Shim your getText(string) method.
Actual Business Project
namespace FakesExample
{
public class MyStaticClass
{
public static string GetText(string name)
{
throw new NullReferenceException();
}
}
}
Your Unit Test Project
using System;
using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace FakesExampleTests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
using (ShimsContext.Create())
{
FakesExample.Fakes.ShimMyStaticClass.GetTextString = (s) =>
{
return "Go away null reference";
};
Console.WriteLine(FakesExample.MyStaticClass.GetText("foo"));
}
}
}
}
I actually ran this so I know it works. What happens is that even though GetText will always throw a NullReferenceException when called, our Shim of it returns our own custom message.
You may have to make a Visual Studio Test Project.
In your Unit Test project, right-click your reference and say "Add Fakes". It will generate all of the Shims and Stubs for your assembly.
Process of removing the static
The best solution is to actually work towards removing the static. You've already hit one major reason to not use them.
Here's how I would go about removing the static and removing the dependency on HttpContext
public interface IResourceRepository
{
string Get(string name);
}
public class HttpContextResourceRepository : IResourceRepository
{
public string Get(string name)
{
return HttpContext.GetGlobalResourceObject("MyResources", name).ToString();
}
}
public class MyFormerStaticClass
{
IResourceRepository _resourceRepository;
public MyFormerStaticClass(IResourceRepository resourceRepository)
{
_resourceRepository = resourceRepository;
}
public string GetText(string name)
{
return _resourceRepository.Get(name);
}
}
I would then leverage Dependency Injection to handle the creation of my HttpContextResourceRepository and MyStaticClass (which should probably also be interfaced) in the actual business code.
For the unit test, I would mock the implementation
[TestFixture]
public class UnitTest1
{
[Test]
public void TestMethod1()
{
var repoMock = new Mock<IResourceRepository>();
repoMock.Setup(repository => repository.Get("foo")).Returns("My Resource Value");
var formerStatic = new MyFormerStaticClass(repoMock.Object);
Console.WriteLine(formerStatic.GetText("foo"));
}
}
Going this route, you can create any number of IResourceRepository implementations and swap them whenever you want.

How to Mock construction of new objects through Nunit

I want to write a nunit test to test a method but I am not able to mock an object instantiated inside that method.
Here is the code:
public class Converter()
{
public void modifyScore(string convertTo){
ScoreConverter scoreConverter;
if(convertTo.Equals("decimal"){
scoreConverter = new DecimalScoreConverter();
scoreConverter.determineScore();
}
else{
scoreConverter = new IntegerScoreConverter();
scoreConverter.determineScore();
}
}
I want to write a test for modifyScore and want to test which object's method has called.
How can I test this method using nunit?
First of all you should start working against abstractions.
I think this is needed for all mock frameworks.
From the info you gave me, and a couple of assumptions:
Anyway, here we go:
public Interface IConverter
{
IScoreConverter ScoreConverter { get; set; };//use constructorinjection instead
void ModifyScore(string convertTo);
}
public Interface IScoreConverter
{
DetermineScore();
}
I would recommend taking a look at MoQ.
You need to figure out what you want to be returned by the inner object.
For now you don't return any value from ModifyScore, so you have nothing to test.
If you would return e.g. a string, the test could look like this:
var scoreConverterResponse = "theStringYouWantToBeReturned"
var scoreConverterMock = new Mock<IScoreConverter>();
scoreConverterMock.Setup(sc => sc.DetermineScore())
.Returns(scoreConverterResponse);
scoreConverterMock.Verify(sc => sc.DetermineScore(It.IsAny<string>()), Times.AtLeastOnce());
I fixed the naming conventions toom i.e. CamelCase methods.
I wrote this on the fly, so I apologise if there are compile errors.
Unit tests are mostly based on state change. So, the natural course is to:
Do something on a class
Test whether the state of the class changed as expected
Maybe you can consider a change in your code to test the type of scoreConverter:
public class Converter
{
public ScoreConverter scoreConverter { get; set; }
public void modifyScore(string convertTo){
if(convertTo.Equals("decimal"){
scoreConverter = new DecimalScoreConverter();
}
else{
scoreConverter = new IntegerScoreConverter();
}
scoreConverter.determineScore();
}
Your test can then execute the modifyScore() method, and then Assert the type of scoreConverter variable.
If you don't want to make the property public, another option is to make it internal and then add the InternalsVisibleToAttribute, or maybe to use a Factory class and then mock it in the test, as amcdermott pointed out.
Greetings!

Creating unit tests for assuring immutability

I have designed an immutable class, because I want to have value-semantics for it. I wrote a hint into the commentary section of the class
// "This class is immutable, don't change this when adding new features to it."
But I know, sometimes those commentaries are overlooked by other team members, so I would like to create a unit test as an additional safeguard. Any idea how to accomplish this? Can one inspect a class via reflection to make sure only the constructors change it's inner state?
(Using C# 2.0 and NUnit, if that's important for anyone).
An example to back up my comment on how you can use FieldInfo.IsInitOnly recursively to test for immutability.
There may be more special cases to consider like how I have handled string, but it will only give false negatives I believe, i.e. will tell you something is mutable that is not, not the other way around.
The logic is, every field must be readonly and be an immutable type itself. Note that it will not cope with self referential types or circular references.
using System;
using System.Linq;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ImmutableTests
{
[TestClass]
public class AssertImmutableTests
{
[TestMethod]
public void Is_int_immutable()
{
Assert.IsTrue(Immutable<int>());
}
[TestMethod]
public void Is_string_immutable()
{
Assert.IsTrue(Immutable<string>());
}
[TestMethod]
public void Is_custom_immutable()
{
Assert.IsTrue(Immutable<MyImmutableClass>());
}
[TestMethod]
public void Is_custom_mutable()
{
Assert.IsFalse(Immutable<MyMutableClass>());
}
[TestMethod]
public void Is_custom_deep_mutable()
{
Assert.IsFalse(Immutable<MyDeepMutableClass>());
}
[TestMethod]
public void Is_custom_deep_immutable()
{
Assert.IsTrue(Immutable<MyDeepImmutableClass>());
}
[TestMethod]
public void Is_propertied_class_mutable()
{
Assert.IsFalse(Immutable<MyMutableClassWithProperty>());
}
private static bool Immutable<T>()
{
return Immutable(typeof(T));
}
private static bool Immutable(Type type)
{
if (type.IsPrimitive) return true;
if (type == typeof(string)) return true;
var fieldInfos = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var isShallowImmutable = fieldInfos.All(f => f.IsInitOnly);
if (!isShallowImmutable) return false;
var isDeepImmutable = fieldInfos.All(f => Immutable(f.FieldType));
return isDeepImmutable;
}
}
public class MyMutableClass
{
private string _field;
}
public class MyImmutableClass
{
private readonly string _field;
}
public class MyDeepMutableClass
{
private readonly MyMutableClass _field;
}
public class MyDeepImmutableClass
{
private readonly MyImmutableClass _field;
}
public class MyMutableClassWithProperty
{
public string Prop { get; set; }
}
}
You could check that the class is sealed, and using reflection check that each field is read-only (using FieldInfo.IsInitOnly).
Of course, that only ensures shallow immutability - it wouldn't stop someone from putting a List<int> field in there, and then changing the contents of the list.
Not sure if you've heard of NDepend, but this tool allows you to "introspect" over your source code and compiled assemblies and do all sorts of magic including dependency checking and much more.
One such check is a check for immutability. For instance, I have an IImmutable marker interface, and NDepend fails my build if any types have this interface but are mutable, using the following query:
WARN IF Count > 0 IN SELECT TYPES WHERE
Implement "MyCompany.MyAssemblies.Dto.IImmutable" AND
!IsImmutable
You can also configure it to generate violation reports, as well as failing builds.
Obviously this isn't actually a unit test. However, it can be integrated as part of your build, and fail your build just as a unit test would, so I thought I'd mention it!
See here for more info on what it actually does and how.

How do I mock a private field?

I'm really new to mocks and am trying to replace a private field with a mock object. Currently the instance of the private field is created in the constructor. My code looks like...
public class Cache {
private ISnapshot _lastest_snapshot;
public ISnapshot LatestSnapshot {
get { return this._lastest_snapshot; }
private set { this._latest_snapshot = value; }
}
public Cache() {
this.LatestSnapshot = new Snapshot();
}
public void Freeze(IUpdates Updates) {
ISnapshot _next = this.LastestSnapshot.CreateNext();
_next.FreezeFrom(Updates);
this.LastestSnapshot = _next;
}
}
What I'm trying to do is create a unit test that asserts ISnapshot.FreezeFrom(IUpdates) is called from within Cache.Freeze(IUpdates). I'm guessing I should replace the private field _latest_snapshot with a mock object (maybe wrong assumption?). How would I go about that while still retaining a parameterless constructor and not resorting to making LatestSnapshot's set public?
If I'm totally going about writing the test the wrong way then please do point out as well.
The actual implementation of ISnapshot.FreezeFrom itself calls a heirarchy of other methods with a deep object graph so I'm not too keen on asserting the object graph.
Thanks in advance.
I'm almost citing techniques from "Working Effectively with Legacy Code":
Sub-class your class in a unit test and supersede your private variable with a mock object in it (by adding a public setter or in the constructor). You probably have to make the variable protected.
Make a protected getter for this private variable, and override it in testing subclass to return a mock object instead of the actual private variable.
Create a protected factory method for creating ISnapshot object, and override it in testing subclass to return an instance of a mock object instead of the real one. This way the constructor will get the right value from the start.
Parametrize constructor to take an instance of ISnapshot.
I'm not sure that you can do that. If you're wanting to test _next then you're probably going to have to pass it in as a parameter and then in your unit test pass in a Mock object which you can then test using an Expectation. That's what I'd be doing if I were trying to do it in Moq.
As an example of what I might try using the Moq framework:
Mock<ISnapshot> snapshotMock = new Mock<ISnapshot>();
snapshotMock.Expect(p => p.FreezeFrom(expectedUpdate)).AtMostOnce();
Cache c = new Cache(snapshotMock.Object);
c.Freeze(expectedUpdate);
Note: I haven't tried to compile the above code. Its just there to give an example of how I'd approach solving this.
I don't think you'd need to mock private member variables. Isn't the whole idea of mocking that the public interface for an object works as expected? Private variables are implementation details that mocks aren't concerned with.
This answer might be simple, but looking at the code, is there any way in which ISnapshot.FreezeFrom(IUpdates) is not going to be called? Sounds like you want to assert something that will always be true.
As Jason says, mocking is meant for situations where your class depends on SomeInterface to do it's work, and you want to test YourClass in isolation from whichever implementation of SomeInterface you actually use at runtime.
The question to ask is: what are the externally visible effects if this worked?
What happens to all those Snapshots? One option might to initialise the Cache with its first Snapshot from outside, say in the constructor. Another might be to mock whatever it is that the Snapshot calls that matters outside the cache. It depends on what you care that happens.
It might be too late to respond. Anyways. I also had similar problem.
public class Model
{
public ISomeClass XYZ{
get;
private set;
}
}
I required to set value of XYZ in my test case. I resolved the problem using this syntex.
Expect.Call(_model.XYZ).Return(new SomeClass());
_repository.ReplayAll();
In the case above we can do it like this
Expect.Call(_cache.LatestSnapshot).Return(new Snapshot());
_repository.ReplayAll();
You will probably have to refactor your class like this, in order for it to be injected with a different dependency for ISnapshot. Your class will remain to function the same.
public class Cache {
private ISnapshot _lastest_snapshot;
public ISnapshot LatestSnapshot {
get { return this._lastest_snapshot; }
private set { this._latest_snapshot = value; }
}
public Cache() : this (new Snapshot()) {
}
public Cache(ISnapshot latestSnapshot) {
this.LatestSnapshot = latestSnapshot;
}
public void Freeze(IUpdates Updates) {
ISnapshot _next = this.LastestSnapshot.CreateNext();
_next.FreezeFrom(Updates);
this.LastestSnapshot = _next;
}
}
You can simply add "setSnapshot(ISnapshot)" method to the Cache with your mocked class instance.
You can also add a constructor that takes ISnapshot.
Turn Cache into a template as shown below.
template <typename T=ISnapshot>
public class Cache {
private T _lastest_snapshot;
public T LatestSnapshot {
get { return this._lastest_snapshot; }
private set { this._latest_snapshot = value; }
}
public Cache() {
this.LatestSnapshot = new Snapshot();
}
public void Freeze(IUpdates Updates) {
T _next = this.LastestSnapshot.CreateNext();
_next.FreezeFrom(Updates);
this.LastestSnapshot = _next;
}
}
In production code do:
Cache<> foo;//OR
Cache<ISnapshot> bar;
In test code do:
Cache<MockSnapshot> mockFoo;

Categories