How to use NSubstitute and / or AutoFixture to test a specific class

I was hoping that by using AutoFixture and NSubstitue I could use the best that everyone has to provide. I have had some success using NSubstitute on its own, but am completely confused on how to use it in conjunction with AutoFixture.

My code below shows a number of things that I am trying to accomplish, but my main goal here is to execute the following scenario: test the functionality of a method.

  • I expect the constructor to be called with random values ​​(except one, please read point 2.).
  • Either at build time or later I want to change the property value - Data

    .
  • Next call Execute

    and confirm results

The test I'm trying to get is: "should_run_GetCommand_with_provided_property_value"

Any help or link to an article that shows how NSubstitue and AutFixture MUST be used would be great.

Sample code:

using FluentAssertions;
using NSubstitute;
using Ploeh.AutoFixture;
using Ploeh.AutoFixture.AutoNSubstitute;
using Xunit;

namespace RemotePlus.Test
{
    public class SimpleTest
    {
        [Fact]
        public void should_set_property_to_sepecified_value()
        {
            var sut = Substitute.For<ISimple>();
            sut.Data.Returns("1,2");

            sut.Data.Should().Be("1,2");
        }

        [Fact]
        public void should_run_GetCommand_with_provided_property_value()
        {
            /* TODO:  
             * How do I create a constructor with AutoFixture and/or NSubstitute such that:
             *   1.  With completely random values.
             *   2.  With one or more values specified.
             *   3.  Constructor that has FileInfo as one of the objects.
             * 
             * After creating the constructor:
             *   1.  Specify the value for what a property value should be - ex: sut.Data.Returns("1,2");
             *   2.  Call "Execute" and verify the result for "Command"
             * 
             */
            // Arrange
            var fixture = new Fixture().Customize(new AutoNSubstituteCustomization());
//            var sut = fixture.Build<Simple>().Create();  // Not sure if I need Build or Freeze            
            var sut = fixture.Freeze<ISimple>();  // Note: I am using a Interface here, but would like to test the Concrete class
            sut.Data.Returns("1,2");

            // Act
            sut.Execute();

            // Assert (combining multiple asserts just till I understand how to use NSubstitue and AutoFixture properly
//            sut.Received().Execute();
            sut.Data.Should().Be("1,2");
            sut.Command.Should().Be("1,2,abc");
            // Fails with : FluentAssertions.Execution.AssertionFailedExceptionExpected string to be "1,2,abc" with a length of 7, but "" has a length of 0.

        }
    }

    public class Simple : ISimple
    {

        // TODO: Would like to make this private and use the static call to get an instance
        public Simple(string inputFile, string data)
        {
            InputFile = inputFile;
            Data = data;

            // TODO: Would like to call execute here, but not sure how it will work with testing.
        }

        // TODO: Would like to make this private
        public void Execute()
        {
            GetCommand();
            // Other private methods
        }

        private void GetCommand()
        {
            Command = Data + ",abc";            
        }

        public string InputFile { get; private set; }
        public string Data { get; private set; }

        public string Command { get; private set; }


        // Using this, so that if I need I can easliy switch to a different concrete class
        public ISimple GetNewInstance(string inputFile, string data)
        {
            return new Simple(inputFile, data);
        }

    }

    public interface ISimple
    {
        string InputFile { get; }   // TODO: Would like to use FileInfo instead, but haven't figured out how to test.  Get an error of FileNot found through AutoFixture
        string Data { get; }
        string Command { get; }

        void Execute();
    }
}

      

+3


source to share


3 answers


I haven't used AutoFixture very often, but based on some reading and a bit of trial and error, I think you are misinterpreting what will and won't do for you. At a basic level, it will allow you to create a graph of objects, filling in values ​​for you based on object constructors (and possibly properties, but I haven't covered that).

Using the NSubstitute integration does not turn all members of your class into instances of NSubstitute. Instead, it gives the binding framework the ability to create abstract / interface types as placeholders.

Looking at the class you are trying to create, the constructor takes two parameters string

. None of these are abstract types or interfaces, so AutoFixture just generates some values ​​for you and passes them on. This is AutoFixture's default behavior and based on the answer linked by @Mark Seemann in the comments, it is by design. There are various options for work that you can implement if it really matters to you, and I will not repeat here.

In your comments, you have indicated what you really want to pass FileInfo

to your constructor. This causes AutoFixture's problem as its constructor takes a string, and hence AutoFixture provides it with an arbitrary generated string, which is a non-existent file, which is why you get an error. It looks like a good thing to try and isolate yourself for testing, so it might be useful for NSubstitute. With this in mind, I'm going to suggest that you rewrite your classes and test something like this:

Wrap the class first FileInfo

(note that depending on what you are doing, you might want to actually wrap the methods from FileInfo that you want instead of exposing it as a property so you can actually isolate yourself from the filesystem, but this will do for now):

public interface IFileWrapper {
    FileInfo File { get; set; }
}

      

Use this in your frontend ISimple

instead of string

(notice I removed from Execute, since you don't seem to need it):



public interface ISimple {
    IFileWrapper InputFile { get; }   
    string Data { get; }
    string Command { get; }
}

      

Write Simple

to implement the interface (I didn't tackle the private constructor issue or your call to Execute in the constructor):

public class Simple : ISimple {

    public Simple(IFileWrapper inputFile, string data) {
        InputFile = inputFile;
        Data = data;
    }

    public void Execute() {
        GetCommand();
        // Other private methods
    }

    private void GetCommand() {
        Command = Data + ",abc";
    }

    public IFileWrapper InputFile { get; private set; }
    public string Data { get; private set; }

    public string Command { get; private set; }
}

      

And then the test:

public void should_run_GetCommand_with_provided_property_value() {
    // Arrange
    var fixture = new Fixture().Customize(new AutoNSubstituteCustomization());

    // create and inject an instances of the IFileWrapper class so that we 
    // can setup expectations
    var fileWrapperMock = fixture.Freeze<IFileWrapper>();

    // Setup expectations on the Substitute.  Note, this isn't needed for
    // this test, since the sut doesn't actually use inputFile, but I've
    // included it to show how it works...
    fileWrapperMock.File.Returns(new FileInfo(@"c:\pagefile.sys"));


    // Create the sut.  fileWrapperMock will be injected as the inputFile
    // since it is an interface, a random string will go into data
    var sut = fixture.Create<Simple>();

    // Act
    sut.Execute();


    // Assert - Check that sut.Command has been updated as expected
    Assert.AreEqual(sut.Data + ",abc", sut.Command);

    // You could also test the substitute is don't what you're expecting
    Assert.AreEqual("pagefile.sys", sut.InputFile.File.Name);
}

      

I am not using the quick statements above, but you should be able to translate ...

+6


source


I actually managed to find a solution by realizing that I didn't need to use AutoFixture for my current scenario.

I had to make some changes to my code:

  • Added default constructor.
  • The methods and properties that I want to expose as "virtual" by default are marked.

Ideally I don't want to do this, but it's enough to get me started and keep moving forward.



Links that helped a lot:

Modified code:

using FluentAssertions;
using NSubstitute;
using Ploeh.AutoFixture;
using Ploeh.AutoFixture.AutoNSubstitute;
using Xunit;
using Xunit.Abstractions;

namespace Try.xUnit.Tests
{
    public class TestingMethodCalls
    {
        private readonly ITestOutputHelper _output;

        public TestingMethodCalls(ITestOutputHelper output)
        {
            _output = output;
        }


        [Fact]
        public void should_set_property_to_sepecified_value()
        {
            var sut = Substitute.For<ISimple>();
            sut.Data.Returns("1,2");

            sut.Data.Should().Be("1,2");
        }

        [Fact (Skip="Don't quite understand how to use AutoFixture and NSubstitue together")]
        public void should_run_GetCommand_with_provided_property_value_old()
        {
            /* TODO:  
             * How do I create a constructor with AutoFixture and/or NSubstitute such that:
             *   1.  With completely random values.
             *   2.  With one or more values specified.
             *   3.  Constructor that has FileInfo as one of the objects.
             * 
             * After creating the constructor:
             *   1.  Specify the value for what a property value should be - ex: sut.Data.Returns("1,2");
             *   2.  Call "Execute" and verify the result for "Command"
             * 
             */
            // Arrange
            var fixture = new Fixture().Customize(new AutoNSubstituteCustomization());
//            var sut = fixture.Build<Simple>().Create();  // Not sure if I need Build or Freeze            
            var sut = fixture.Freeze<ISimple>();  // Note: I am using a Interface here, but would like to test the Concrete class
            sut.Data.Returns("1,2");

            // Act
            sut.Execute();

            // Assert (combining multiple asserts just till I understand how to use NSubstitue and AutoFixture properly
//            sut.Received().Execute();
            sut.Data.Should().Be("1,2");
            sut.Command.Should().Be("1,2,abc");
            // Fails with : FluentAssertions.Execution.AssertionFailedExceptionExpected string to be "1,2,abc" with a length of 7, but "" has a length of 0.
        }

        /* Explanation:
         * Create a construtor without any arguments.
         *      Had to create a parameterless constructor just for testing purposes (would like to improve on this)
         * Specify a default value for the desired method or property.
         *      It is necessary that the property or method has to be virtual.
         *      To specify that the based mehod should be call use the "DoNotCallBase" before the "Returns" call
         */ 
        [Fact]
        public void should_run_GetCommand_with_provided_Method_value()
        {
            // Arrange
            var sut = Substitute.ForPartsOf<Simple>();
            sut.When(x => x.GetData()).DoNotCallBase();
            sut.GetData().Returns("1,2");

            // Act
            sut.Execute();

            // Assert
            sut.Received().GetData();

            sut.Data.Should().Be("1,2");
            sut.Command.Should().Be("1,2,abc");
        }

        [Fact]
        public void should_run_GetCommand_with_provided_Property_value()
        {

            // Arrange
            var sut = Substitute.ForPartsOf<Simple>();
            sut.When(x => { var data = x.Data; }).DoNotCallBase();
            sut.Data.Returns("1,2");

            // Act
            sut.Execute();

            // Assert
            sut.Received().GetData();
            _output.WriteLine(sut.Command);

            sut.Data.Should().Be("1,2");
            sut.Command.Should().Be("1,2,abc");
        }

    }

    public class Simple : ISimple
    {
        public Simple(){}

        // TODO: Would like to make this private and use the static call to get an instance
        public Simple(string inputFile, string data)
        {
            InputFile = inputFile;
            InputData = data;

            // TODO: Would like to call execute here, but not sure how it will work with testing.
        }

        public virtual string GetData()
        {
            // Assume some manipulations are done
            return InputData;
        }

        // TODO: Would like to make this private
        public void Execute()
        {
            Data = GetData();
            GetCommand();
            // Other private methods
        }

        private void GetCommand()
        {
            Command = Data + ",abc";            
        }

        string InputData { get; set; }

        public string InputFile { get; private set; }


        public virtual string Data { get; private set; }
        public string Command { get; private set; }


        // Using this, so that if I need I can easliy switch to a different concrete class
        public ISimple GetNewInstance(string inputFile, string data)
        {
            return new Simple(inputFile, data);
        }

    }    

    public interface ISimple
    {
        string InputFile { get; }   // TODO: Would like to use FileInfo instead, but haven't figured out how to test.  Get an error of FileNot found through AutoFixture
        string Data { get; }
        string Command { get; }

        void Execute();
    }

}

      

+1


source


I am posting this as a separate answer because it is more of a criticism of the approach than a direct answer to your original question. In my other answer, I tried to directly answer your AutoFixture / NSubstitute questions, assuming you are currently trying to learn them within frameworks.

In any case, you don't need to use any of these frameworks to achieve what you are doing, and in a sense it is easier not to. Looking at this test:

public void should_set_property_to_sepecified_value()
{
    var sut = Substitute.For<ISimple>();
    sut.Data.Returns("1,2");

    sut.Data.Should().Be("1,2");
}

      

This does not test your class at all (other than compile-time checking), indeed you are testing NSubstitute. You test this if you tell NSubstitute to return a value for the property it does.

Generally speaking, try to avoid mocking the class you are testing. If you need to do this, then there is a good chance you need to rethink your design. Mocking is really useful for providing dependencies in your class that you can control to influence the behavior of your class. If you start modifying the behavior of the class you are testing using mocks, it is very easy to get confused about what you are actually testing (and create very fragile tests).

Since you are dealing with basic types and non-nested objects it is easy to create + test your objects at this point without using something like AutoFixture / NSubstitute. You can look like it looks like what you are hoping for:

public interface ISimple {
    string InputFile { get; }   
    string Data { get; }
    string Command { get; }
}

public class Simple : ISimple {
    private Simple(string inputFile, string data) {
        InputFile = inputFile;
        Data = data;
    }

    private void Execute() {
        GetCommand();
    }

    private void GetCommand() {
        Command = Data + ",abc";
    }

    public string InputFile { get; private set; }
    public string Data { get; private set; }

    public string Command { get; private set; }


    // Note.. GetNewInstance is static and it calls the Execute method
    static public ISimple GetNewInstance(string inputFile, string data) {
        var simple =  new Simple(inputFile, data);
        simple.Execute();
        return simple;
    }

}

      

And your test will look like this:

[Test]
public void should_run_GetCommand_with_provided_property_value() {
    // Arrange
    var inputFile = "someInputFile";
    var data = "1,2";
    var expectedCommand = "1,2,abc";


    // Act
    // Note, I'm calling the static method to create your instance
    var sut = Simple.GetNewInstance(inputFile, data);

    // Assert
    Assert.AreEqual(inputFile, sut.InputFile);
    Assert.AreEqual(data, sut.Data);
    Assert.AreEqual(expectedCommand, sut.Command);
}

      

I left Execute

outside the object constructor because it looks a bit like it will do too much. I'm not a big fan of doing much other than basic setting in constructors, especially if there's a chance that you might call virtual methods . I also made it static GetNewInstance

so that it can be called directly (otherwise you have to create Simple

to call GetNewInstance

on it, which seems wrong) ...

While I have shown above how your code can work the way you want it, I would suggest that you can change the constructor Simple

to an internal rather than a private one. This will allow you to create a factory to create instances. If you have something like this:

public interface IMyObjectFactory {
    ISimple CreateSimple(string inputFile, string data);
}

public class MyObjectFactory {
    ISimple CreateSimple(string inputFile, string data) {
        var simple =  new Simple(inputFile, data);
        simple.Execute();
        return simple;
    }
}

      

This allows you to safely create objects that require methods to be called on them. You can also introduce replacements IMyObjectFactory

that return the replacement ISimple

in future classes that depend on the class Simple

. This will help you isolate your classes from the behavior of the main class (which can access the filesystem) and make stubbing answers easier for you.

+1


source







All Articles