Skip to content

Instantly share code, notes, and snippets.

@jcansdale
Last active January 24, 2020 19:56
Show Gist options
  • Save jcansdale/de58c2b2c389851f72b00ef525be820c to your computer and use it in GitHub Desktop.
Save jcansdale/de58c2b2c389851f72b00ef525be820c to your computer and use it in GitHub Desktop.
Unit testing challenge

I'm looking for the cleanest way to make the test below pass.

The rules are:

  1. It must be a unit test (so don't touch the file system).
  2. The public signature for CodeUnderTest must not be changed. can be extended not reduced
  3. You're allowed to use DI/your favorite mocking framework.
  4. You can only add code where you see /**/.
        [Test]
        public void Test()
        {
            /**/
            var text = CodeUnderTest.GetUpperText("foo.txt" /**/);

            Assert.That(text, Is.EqualTo("BAR"));
            /**/
        }

        public class CodeUnderTest
        {
            /**/
            public static string GetUpperText(string path /**/)
            {
                var text = File.ReadAllText(path);
                return text.ToUpperInvariant();
            }
            /**/
        }

Please comment below or tweet me @jcansdale.

@PMBjornerud
Copy link

Looks like a method containing both file system operations and business logic. I'd split them.

One method (impure) for getting the file content, or null if no file.
One method (pure) containing the rules for how to format the result.

These methods would be standalone and you would only have to change one of them if the data layer or business rules changed. Integration tests for the first. Unit tests for the second (which often contains the edge cases and complex logic).

I remember one article that described an idea as "dependency elimination", which I guess this relates to.
http://qualityisspeed.blogspot.no/2014/09/beyond-solid-dependency-elimination.html

(And since this is the internet, obligatory troll content: "Mocking considered harmful" ;)

@ploeh
Copy link

ploeh commented Sep 26, 2016

How would that look in F#? That question triggered a blog post, but the summary is this:

// string -> string
let getUpperText path =
    path
    |> Some
    |> Option.filter File.Exists
    |> Option.map (File.ReadAllText >> getUpper)
    |> Option.defaultIfNone "DEFAULT"

Apart from getUpper there's nothing else to test 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment