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.
Related
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.
Is there some kind of way to let AutoFixture create properties with an internal setter?
I've looked at the AutoFixture source and found that in the AutoPropertiesCommand the GetProperties method checks whether a property has GetSetMethod() != null.
With an internal setter this returns null, unless you set the ignorePublic argument to true.
The easiest thing would of course be to make the setter public but in the project I'm working on this just wouldn't be the right solution.
Below is a simplified piece of code from the project as an example.
public class Dummy
{
public int Id { get; set; }
public string Name { get; internal set; }
}
public class TestClass
{
[Fact]
public void Test()
{
var dummy = new Fixture().Create<Dummy>();
Assert.NotNull(dummy.Name);
}
}
Ideally, the tests shouldn't have to interact with the internal members of a class, since they are explicitly excluded from its public API. Instead, these members would be tested indirectly by the code paths initiated through the public API.
However, if this isn't feasible in your particular situation, a possible workaround could be to explicitly assign a value to the internal properties from within the tests.
You can do that in one of two ways:
By exposing all internal members within the assembly to the test project using the InternalsVisibleTo attribute.
By representing the modifiable state of the class in a specific interface and implement that explicitly.
In your example, option 1 would be:
// [assembly:InternalsVisibleTo("Tests")]
// is applied to the assembly that contains the 'Dummy' type
[Fact]
public void Test()
{
var fixture = new Fixture();
var dummy = fixture.Create<Dummy>();
dummy.Name = fixture.Create<string>();
// ...
}
Option 2, instead, would be something like:
public class Dummy : IModifiableDummy
{
public string Name { get; private set; }
public void IModifiableDummy.SetName(string value)
{
this.Name = value;
}
}
[Fact]
public void Test()
{
var fixture = new Fixture();
var dummy = fixture.Create<Dummy>();
((IModifiableDummy)dummy).SetName(fixture.Create<string>());
// ...
}
Option 1 is fairly quick to implement, but has the side effect of opening up all internal members within the assembly, which may not be what you want.
Option 2, on the other hand, allows you to control what part of the object's state should be exposed as modifiable, while still keeping it separated the object's own public API.
As a side note, I'd like to point out that, since you're using xUnit, you can take advantage of AutoFixture's support for Data Theories to make your tests slightly more terse:
[Theory, AutoData]
public void Test(Dummy dummy, string name)
{
((IModifiableDummy)dummy).SetName(name);
// ...
}
If you prefer to set the Name property to a known value while still keeping the rest of the Dummy object anonymous, you have also the possibility to combine the two within the same Data Theory:
[Theory, InlineAutoData("SomeName")]
public void Test(string name, Dummy dummy)
{
((IModifiableDummy)dummy).SetName(name);
// ...
}
Is it possible to skip all tests from a specific class like in NUnit
[TestFixture]
[Ignore("Reason")]
public class TestClass {
}
No - there is no such facility at present, and the last time it was requested it was considered too low value to add,
One quick way of achieving the effect in xUnit is to comment out the public - private classes are not reflected over (obviously it won't appear on the skip list that way though).
UPDATE: Another way is to put a TraitAttribute on the class and then (assuming you're using the xunit.console runner) filter it out by running with /-trait traitName. (e.g. you can achieve ExplicitAttribute, some aspects of the BDD frameworky technique of Pending tests and similar semantics that way - of course the big problem is they don't show up in any reports when using any of these filtering techniques)
UPDATE 2: You can do
const string skip = "Class X disabled";
[Fact(Skip=skip)]
void Test() {}
Then you can change to to const string skip = null to undo the skip. The (dis)advantage of this is that the test is still shown as a Skipped test in the test list, generally with a reason included in the test run report (vs making it private which makes it likely to be forgotten)
Here is my hack to avoid error xUnit1000: Test classes must be public (checked on single Fact, I think Theories can be hacked this way, too).
// Uncomment to enable tests
//public class FactSwitch : FactAttribute { } // public! ahh, a bug!
// Uncomment to disable tests
internal class FactSwitch : Attribute { }
public class MyTests
{
[FactSwitch]
public void MyTest1()
{
"it".ShouldBe("it");
}
}
(3 years later)
While searching for the same solution I found there are better ways to do the same.
Let's rewrite the example above in a way Ruben Bartelink suggested (continuation of his idea).
public class MyTests
{
//const string SkipOrNot = null; // Run all tests
const string SkipOrNot = "reason"; // Skip all tests
[Fact(Skip = SkipOrNot)]
public void MyTest1()
{
"it".ShouldBe("it");
}
}
Nathan Cooper suggested a good improvement for my idea:
public class MyTests
{
// Uncomment to disable tests
//private class FactAttribute : Attribute { }
[Fact]
public void MyTest1()
{
"it".ShouldBe("it");
}
}
So I like both ideas from Ruben and Nathan. There is a subtle difference between using Skip="something" (Ruben) and not using Skip at all. Using "Skip" will put all your tests in a "Skipped tests" warning zone, while "FactAttribute : Attribute" will hide them.
I've found yet another way of temporary disabling entire class without compiler warning.
Disabled:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "xUnit1000:Test classes must be public", Justification = "Disabled")]//*/
/*
public /**/class DatabaseTests
{
}
to enable move the /* one line up (i.e. using alt+up):
/*
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "xUnit1000:Test classes must be public", Justification = "Disabled")]//*/
public /**/class DatabaseTests
{
}
Note that using full namespace path for SupressMessage does not mess up with your usings.
You need to set the your class access level as as internal and surpress message as #Miq did:
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "xUnit1000:Test classes must be public", Justification = "Disabled")]
internal class MyClassThatIsNotATestClass
{ ... }
You can create LocalOnlyFactAttribute
public class LocalOnlyFactAttribute : FactAttribute
{
//uncomment to run on local
//const string skip = null;
//keep this to avoid slow running tests on other env
const string skip = "Disabled slow running tests.";
public override string Skip { get => skip; set => base.Skip = value; }
}
As far as I know, the simplest way to dynamically skip a whole xUnit test class at runtime is to use the TestFrameworkAttribute at the assembly level, to point to a class that implements the ITestFramework interface (or inherits from XunitTestFramework, which is simpler) and which overrides the CreateDiscoverer() method to return another class, that implements the ITestFrameworkDiscoverer interface (or inherits from XunitTestFrameworkDiscoverer, which is simpler), where you can finally override the IsValidTestClass() method, to decide whether a class should be skipped or not.
Here is some sample code:
[assembly: TestFramework("MyNamespace.Xunit.MyTestFramework", "MyAssembly")]
namespace MyNamespace.Xunit
{
public class MyTestFramework : XunitTestFramework
{
public MyTestFramework(IMessageSink messageSink)
: base(messageSink)
{
}
protected override ITestFrameworkDiscoverer CreateDiscoverer(
IAssemblyInfo assemblyInfo)
=> new MyTestFrameworkDiscoverer(
assemblyInfo,
SourceInformationProvider,
DiagnosticMessageSink);
}
public class MyTestFrameworkDiscoverer : XunitTestFrameworkDiscoverer
{
public MyTestFrameworkDiscoverer(
IAssemblyInfo assemblyInfo,
ISourceInformationProvider sourceProvider,
IMessageSink diagnosticMessageSink,
IXunitTestCollectionFactory collectionFactory = null)
: base(
assemblyInfo,
sourceProvider,
diagnosticMessageSink,
collectionFactory)
{
}
protected override bool IsValidTestClass(ITypeInfo type)
=> base.IsValidTestClass(type) &&
FilterType(type);
protected virtual bool FilterType(ITypeInfo type)
{
// Insert your custom filter conditions here.
return true;
}
}
}
Tested with xUnit 2.4.1.
We are using it in Pomelo.EntityFrameworkCore.MySql (see AssemblyInfo.cs and MySqlXunitTestFrameworkDiscoverer.cs) (a bit more complex than the sample code here).
You could achieve this through a custom ITestClassCommand.
See http://mariangemarcano.blogspot.be/2010/12/xunitnet-running-tests-testcategory.html
Here's another hack that requires minimal changes to code
using FactAttribute = System.Runtime.CompilerServices.CompilerGeneratedAttribute;
using TheoryAttribute = System.Runtime.CompilerServices.CompilerGeneratedAttribute;
Any compatible attribute can be used for the replacement.
If you also use the InlineDataAttribute then you'll need to define a replacement as I don't think there's an existing compatible attribute.
using InlineDataAttribute = DummyDataAttribute;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
internal class DummyDataAttribute : Attribute
{
public DummyDataAttribute(params object[] data)
{
}
}
Adding a reason almost after one year after the initial question. I have a set of tests which are calling real server apis, and I would like to run then on demand. With nUnit, it has Ignore attribute : with that set, test runner will skip those tests, but I can still manually run it.
xUnit has no such feature. The nearest one is setting such a class level attribute, and comment it out when I want to run it.
Consider creating LocalOnlyFactAttribute, which can be reused across multiple test files.
public class LocalOnlyFactAttribute : FactAttribute
{
//uncomment to run on local
//const string skip = null;
//keep this to avoid slow running tests on other env
const string skip = "Disabled slow running tests.";
public override string Skip { get => skip; set => this.Skip = value; }
}
In classes whose instances I persist using an object database, I keep having to do this:
private string _name;
public string Name
{
get { return this._name; }
set { _name = value; this.Save(); }
}
whereas I would much rather type this:
[PersistedProperty(Name)]
private string _name;
where the PersistedProperty attributes generates a Getter and Setter just like the default [Property()] attribute, except I want to add a line of code to the generated Setter.
Is there a way I can create an attribute which does this? Hopefully , which works with Intellisense.
How does the default [Property()] attribute even do it's stuff? If I saw the code I could graft that...
Note: I am actually doing this in Boo, but thought I'd give c# code as more people might be willing to answer that, however, if there is a Boo specific solution, I'm all ears!
Update:
My aim was simply to reduce typing and clutter. It turns out the simplest way of doing this was with a script which generates partial classes based on markup in my classes.
Auto-generating source code from markup (in tandem with partial classes) is easy, and actually looks like an extremely promising way to get round some of the problems we normally try to solve with inheritance and generic types.
This requires aspect oriented programming. While not directly supported in .NET, it can be done via third party tooling, such as PostSharp.
For intellisense to work, however, this must be done in a library, as the (final) compiled code will be unrolled into the full property getter/setter.
Not easy to implement using attributes IMO.
Maybe you could use another approach, such as an extension method:
// Extension method that allows updating a property
// and calling .Save() in a single line of code.
public static class ISaveableExtensions
{
public static void UpdateAndSave<T>(
this ISaveable instance,
Expression<Func<T>> propertyExpression, T newValue)
{
// Gets the property name
string propertyName = ((MemberExpression)propertyExpression.Body).Member.Name;
// Updates its value
PropertyInfo prop = instance.GetType().GetProperty(propertyName);
prop.SetValue(instance, newValue, null);
// Now call Save
instance.Save();
}
}
...
// Some interface that implements the Save method
public interface ISaveable
{
void Save();
}
...
// Test class
public class Foo : ISaveable
{
public string Property { get; set; }
public void Save()
{
// Some stuff here
Console.WriteLine("Saving");
}
public override string ToString()
{
return this.Property;
}
}
...
public class Program
{
private static void Main(string[] args)
{
Foo d = new Foo();
// Updates the property with a new value, and automatically call Save
d.UpdateAndSave(() => d.Property, "newValue");
Console.WriteLine(d);
Console.ReadKey();
}
}
It's type-safe, autocompletion-friendly, but it requires more code than just .Save() in all setters, so not sure I would use it actually...
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());
}
}