Unit Testing in C#
  • Unit testing in C#
  • Unit testing
    • What to test
    • When to test
    • Qualities of a good unit test suite
    • Qualities of a good unit test
    • Dealing with dependencies
    • Running the tests
  • NUnit
    • Quick glance at NUnit
    • Creating a NUnit test project
    • Anatomy of a test fixture
    • Lifecycle of a test fixture
    • Assertions
    • Asynchronous executions
    • Parameterized tests
    • Assumptions
    • Describing your tests
  • Moq
    • Quick glance at Moq
    • Method arguments
    • Method calls
    • Properties
    • Results
    • Callbacks
    • Exceptions
    • Events
    • Verifications
    • Base class
    • Mock customization
    • Implicit mocks
    • Mock repository
    • Custom matchers
    • Multiple interfaces
    • Protected members
    • Generic methods
    • Delegates
  • AutoFixture
    • Quick glance at AutoFixture
    • Fixture
    • Create and Build
    • Type customization
    • Data annotations
    • Default configurations
    • Building custom types
    • Relays
    • Tricks
    • Idioms
    • Integration with NUnit
    • Integration with Moq
    • Combining AutoFixture with NUnit and Moq
    • Extending AutoFixture
  • Advanced topics
    • Testing HttpClient
Powered by GitBook
On this page
  • Random value from list of valid values
  • Random valid Encoding
  • Working with streams
  • NullStream
  • MemoryStream
  • Working with dictionaries
  1. AutoFixture

Tricks

This page contains a list of tips and tricks to be used when dealing with special scenarios with AutoFixture

Random value from list of valid values

In case a certain type can assume a subset of the valid values, an instance of the ElementsBuilder<T> class can be used to provide AutoFixture with the values to fish from.

[Test]
public void ElementsBuilder_returns_one_of_specified_values()
{
    // ARRANGE
    var fixture = new Fixture();
    var values = new[] { "Foo", "Bar", "Baz" };
    fixture.Customizations.Add(new ElementsBuilder<string>(values));

    // ACT
    var value = fixture.Create<string>();

    // ASSERT
    Assert.That(value, Is.AnyOf(values));
}

It's important to note that a setup like the one above affects every instance of the customized type: this means that every instance of the customized type generated by this fixture will be picked from the specified values.

Random valid Encoding

By default, when requested an instance of type Encoding, AutoFixture always returns Encoding.UTF8.

It is possible to override the default setup by registering all supported encodings. To do so, we add an instance of ElementsBuilder<EncodingInfo> to the set of customizations. We can then use Register to instruct AutoFixture to extract an Encoding from the random EncodingInfo received.

fixture.Customizations.Add(new ElementsBuilder<EncodingInfo>(Encoding.GetEncodings()));

fixture.Register<EncodingInfo, Encoding>((EncodingInfo ei) => ei.GetEncoding());

Furthermore, we can use the above configuration to configure the string property of an object that could be parsed from a text file.

fixture.Customize<Options>(c => c.With(p => p.EncodingName, (Encoding encoding) => encoding.WebName));

Here is the class used for this example

public class Options
{
    public string EncodingName { get; set; }
}

Working with streams

Classes exposing properties of type Stream require special setup.

Here are some configurations that can be used when working with streams. The best setup might vary from case to case.

The following class will be used for the snippets below

public class Options
{
    public Stream InputStream { get; set; }
}

NullStream

The easiest scenario: every Stream property receives the singleton value of the NullStream class.

fixture.Inject<Stream>(Stream.Null);

If a more targeted approach is needed, the construct With can be used.

fixture.Customize<Options>(c => c.With(p => p.InputStream, Stream.Null));

MemoryStream

In case the system under test expects some data out of the stream, the MemoryStream can be used to return the test data.

fixture.Register<byte[], Stream>((byte[] data) => new MemoryStream(data));

In the case the stream is expected to contain a random string, this setup can be used.

fixture.Register<string, Stream>((string data) => 
{
    var bytes = Encoding.UTF8.GetBytes(data);
    return new MemoryStream(bytes);
});

Finally, if the stream is expected to contain the serialized version of some data, this setup can be used (the example uses Newtonsoft.Json to serialize the payload)

fixture.Register<Data, Stream>((Data data) => 
{   
    var serializer = new JsonSerializer();

    var ms = new MemoryStream();
    var sr = new StreamWriter(ms);

    serializer.Serialize(sr, data);

    sr.Flush();

    return ms;
});

public class Data
{
    public int Value { get; set; }

    public string Message { get; set; }
}

These setups can also be applied on a specific property of a specific type using the construct With.

Working with dictionaries

Normally dictionaries are created and filled with items whose key and value are randomly generated. Sometimes a dictionary with specific keys are needed.

Considering the class below,

public class Options
{
    public IReadOnlyDictionary<string, int> Values { get; set; }
}

The snippet below configures the type Options so that its instances have the property Values set to a dictionary containing an item with a well-known key and a value generated by AutoFixture.

fixture.Customize<Options>(c => c.With(p => p.Values, (int value) => new Dictionary<string, int> { ["my key"] = value }));
PreviousRelaysNextIdioms

Last updated 4 years ago

This setup will return a stream containing a certain amount of bytes. The amount is controlled by the property.

Fixture.RepeatCount