A class to randomly generate values. Useful for unit tests. Powered by AutoFixture.
Install-Package ConnelHooley.TestHelpers
Returns a value created by AutoFixture
.
var randomMailAddress = TestHelper.Generate<MailAddress>();
To find out how to configure the AutoFixture
instance inside the TestHelper
please go the Configuration section.
Returns an exception with a randomly generated message.
var randomException = TestHelper.GenerateException();
Returns a random boolean.
var randomBool = TestHelper.GenerateBool();
Returns a random date between 1000 days in the past and 1000 days in the future.
var randomDate = TestHelper.GenerateDateTime();
Returns a random date between 1000 days in the past and 1007 days in the future on a certain day.
var randomMonday = TestHelper.GenerateDateTimeByWeekDay(DayOfWeek.Monday);
Returns a random number. Includes negative values.
var randomNumber = TestHelper.GenerateNumber();
Returns a random number below a certain value. Includes negative values.
var randomNumberBelow100 = TestHelper.GenerateNumberBelow(100);
Returns a random number above a certain value. Includes negative values.
var randomNumberAbove100 = TestHelper.GenerateNumberAbove(100);
Returns a random number between two values. Both the lower and upper bounds are inclusive.
var randomNumberBetween50and100 = TestHelper.GenerateNumberBetween(50, 100);
Returns a random item from an IEnumerable
.
var items = new[] {"hello", "world"};
var helloOrWorld = TestHelper.ChooseRandomItem(items);
It is also exposed as an extension method.
var items = new[] {"hello", "world"};
var helloOrWorld = items.ChooseRandomItem();
Removes a random item from a List
and returns the removed item.
var items = new[] {"hello", "world"};
var helloOrWorld = TestHelper.TakeRandomItem(items);
It is also exposed as an extension method.
var items = new[] {"hello", "world"};
var helloOrWorld = items.TakeRandomItem();
Randomly mix-cases a string so that some of its letters are uppercase and some are lowercase.
var randomMixedCase = TestHelper.RandomCaseString("hello world");
It is also exposed as an extension method.
var x = "hello world";
var randomMixedCase = x.ToRandomCase();
Returns a random string made up of letters from the alphabet (uppercase and lowercase), numbers and some special characters.
var randomString = TestHelper.GenerateString();
Returns a random string made up of the chars in the given string.
var randomStringMadeUpOfNumbers = TestHelper.GenerateStringFrom(TestHelper.Numbers);
Returns a string containing 1 to 50 spaces.
var randomWhitespace = TestHelper.GenerateWhitespaceString();
Returns the given string with 1 to 50 spaces prepended and appended to it.
var helloWorldWrappedInRandomWhitespace = TestHelper.WrapStringInWhitespace("helloworld");
It is also exposed as an extension method.
var x = "helloworld";
var helloWorldWrappedInRandomWhitespace = x.WrapStringInWhitespace();
Runs the creator function between 2 and 100 times and returns the results in an IEnummerable
.
var randomStrings = TestHelper.GenerateMany(TestHelper.GenerateString);
You can also specify how many times to run the creator:
var fiftyRandomStrings = TestHelper.GenerateMany(50, TestHelper.GenerateString);
Returns a random enum.
var randomDayOfWeek = TestHelper.GenerateEnum<DayOfWeek>();
You can also specify values to exclude:
var randomWeekDay = TestHelper.GenerateEnum(DayOfWeek.Saturday, DayOfWeek.Sunday);
Returns a random GUID.
var randomGuid = TestHelper.GenerateGuid();
Returns a function that in turn returns random types.
var typeGenerator = TestHelper.GetRandomTypeGenerator();
var type1 = typeGenerator();
var type2 = typeGenerator();
The method works by getting the assembly of the Type
type in the System namespace. It then gets all the exported types for that assembly. The returned Func
randomly selects items from the exported types when it is ran. It removes items from the list as it goes to prevent duplicates. The Func
will throw when there are no more types to pick from.
There are two ways of configuring the TestHelper.
So far, we have seen usage of the static TestHelper
class. It is also possible to create a TestHelperInstance
class that contains its own configuration.
For example:
public class Program
{
public static void Main()
{
var testHelper = new TestHelperInstance(x =>
{
x.Register<User>(() => new User
{
Id = TestHelper.GenerateNumber(),
Username = "ExampleUserName"
});
});
var user = testHelper.Generate<User>();
Console.WriteLine(user.Username); // Prints "ExampleUserName"
Console.WriteLine(user.Id); // Prints random ID
Console.ReadLine();
}
}
public class User
{
public int Id { get; set; }
public string Username { get; set; }
}
This is useful for when a group of tests needs a particular configuration. The TestHelperInstance
class has all the same methods as the static TestHelper
class, although apart from the Generate<T>()
method, they all just call the static TestHelper
under the hood.
Sometimes you always want to create a specified type the same way throughout a test project, or even all your test projects. To do this both the static TestHelper
class and the TestHelperInstance
scan for an interface called ITestHelperConfigurator
:
- The test helpers load any DLLs that end with
.TestHelperSupport.dll
. - They then query all the currently loaded assemblies for implementations of
ITestHelperConfigurator
. - These Configurators are then run to configure the test helpers.
An example of what using a Configurator would like:
public class Program
{
public static void Main()
{
Console.WriteLine(TestHelper.Generate<string>()); // Prints "hello"
Console.WriteLine(TestHelper.Generate<int>()); // Prints 5
Console.ReadLine();
}
}
public class TestHelperConfigurator : ITestHelperConfigurator
{
public void Configure(ITestHelperContext x)
{
x.Register(() => "hello");
x.Register(() => 5);
}
}
The TestHelperInstance
loads in any ITestHelperConfigurator
implementations and then loads in its own configuration. This means that if a TestHelperInstance
registers a type in the action passed into its constructor, this registration will be used instead of any found in any Configurators.
For example:
public class Program
{
public static void Main()
{
var testHelper = new TestHelperInstance(x =>
{
x.Register(() => "world");
});
Console.WriteLine(testHelper.Generate<string>()); // Prints "world"
Console.ReadLine();
}
}
public class TestHelperConfigurator : ITestHelperConfigurator
{
public void Configure(ITestHelperContext x)
{
x.Register(() => "hello");
}
}
If you create a type that should always be created in a certain way, you can create a NuGet package that references your type and includes an ITestHelperConfigurator
implementation.
Below is an example type I could publish as a NuGet package called UpperCaseString
:
public class UpperCaseString
{
private readonly string _value;
public UpperCaseString(string x)
{
if(x != x.ToUpperInvariant()) throw new ArgumentException("String must be uppercase");
_value = x;
}
public static implicit operator string(UpperCaseString d) => d._value;
}
I could then publish the following Configurator as a separate NuGet package called UpperCaseString.TestHelperSupport
:
public class UpperCaseStringTestHelperConfigurator : ITestHelperConfigurator
{
public void Configure(ITestHelperContext x)
{
x.Register(() => new UpperCaseString(x.Generate<string>().ToUpperInvariant()));
}
}
Calling it UpperCaseString.TestHelperSupport
ensures that the test helper classes load in the assembly even if no other code references it.
The test helper support package only needs to reference the ConnelHooley.TestHelpers.Abstractions
package. Then when anyone uses UpperCaseString
in their project, they only need to install the support package and the test helper classes will pick up the configurator and successfully generate UpperCaseString
types.