5

I like the suggestion here:

SO question

It suggests using this code:

public class SettingsReader()
{
    public SettingsReader(System.IO.StreamReader reader)
    {
        // read contents of stream...
    }
}

// In production code:
new SettingsReader(new StreamReader(File.Open("settings.xml")));

// In unit test:
new SettingsReader(new StringReader("<settings>dummy settings</settings>"));

I am just wondering what the best practice is to 'supply' large test strings (i.e. several lines of the file to be parsed).

Community
  • 1
  • 1
cs0815
  • 16,751
  • 45
  • 136
  • 299

4 Answers4

3

One common approach is to add a file with the test data to the resources of the unit test assembly and read that data in the unit test.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • Would this not be an integration test as it involves a file somewhere? That's what I would like to avoid ... – cs0815 Jan 16 '13 at 09:00
  • 2
    No, it doesn't involve a physical file on disk. You read the data straight from the resources of your assembly. – Daniel Hilgarth Jan 16 '13 at 09:14
2

For unit tests its best to show the test data directly in the code, instead of using an embedded resource file.

var settings = @"
<settings>
  <a>1</a>
  <b>2</b>
</settings>";

new SettingsReader(new StringReader(settings));
Richard Schneider
  • 34,944
  • 9
  • 57
  • 73
  • Thanks I thought about this. Could I put such data into 'something' else (e.g. app.config) to be able to reuse these 'chunks of data' in other unit tests? – cs0815 Jan 16 '13 at 09:00
  • I feel that unit tests should be self contained. I would just duplicate the "chunks". But if you want to use chunks why not just make the chunks as `internal static string chunk1 = @"..."` of the test class. – Richard Schneider Jan 16 '13 at 09:03
  • 1
    As soon as you have to put escape codes in, it gets really messy putting the strings into the source code. Commonly, our large test strings have a lot of quotes in them, and it becomes really annoying to read and edit them if they are in the source code. – Matthew Watson Jan 16 '13 at 09:25
  • @MatthewWatson: OP has not talked about escape codes. With the `@"` syntax the only character that needs escaping is a double-qoute and in XML double-quotes are interchangable with single-quotes! – Richard Schneider Jan 16 '13 at 09:30
2

Just add a separate file as assembly embedded resource and load it in unit test.

Use Assebmly.GetManifestResourceStream method to load the embedded file.

using (var stream = Assembly.GetExecutingAssembly()
       .GetManifestResourceStream(typeof(YourUnitTest), filename))
using(var reader = new StreamReader(stream))
{
    var fileContent = reader.ReadToEnd();
}
Jakub Konecki
  • 45,581
  • 7
  • 87
  • 126
  • Sounds interesting. Can you add some more meat to this as the link does not help me very much. Thanks. – cs0815 Jan 16 '13 at 09:02
  • Ok just found it: http://stackoverflow.com/questions/6080596/how-can-i-load-this-file-into-an-nunit-test – cs0815 Jan 16 '13 at 09:36
0

The easiest way is to just add a file to the unit test project, and use that. Set the file's properties to "Build Action = None" and "Copy to Output Directory = Copy if newer" and then you can just assume the file is in the same folder as the unit test executable.

I find that putting a large string into the source code itself makes it harder to read because of the way you have to format strings in the source code - especially if the text contains characters that must be escaped. Much nicer to have a text file with all the data, IMHO.

If you would like to share the test data between unit test projects, you can do so by placing the file somewhere under source control and then add to the project a link to the file (rather than a copy of the file). That way you only have one copy of the original source file to maintain.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • 2
    Would this not be an integration test as it involves a file somewhere? That's what I would like to avoid ... – cs0815 Jan 16 '13 at 08:58