简体   繁体   中英

Abstracted Dispose Method not called when using nSubstitute

i have this base (abstract) class:

public abstract class StreamWriterBuilderService : IStreamWriterService
{
    private Stream fs;
    private StreamWriter stream;

    public void WriteLine(
        string stringToWrite )
    {
        if ( stream == null )
        {
            throw new InvalidOperationException( "Tried to call WriteLine on an uninitialised StreamWriterBuilderService" );
        }

        stream.WriteLine( stringToWrite );
        Flush();
    }

    public void Flush()
    {
        if ( stream == null )
        {
            throw new InvalidOperationException( "Tried to call Flush on an uninitialised StreamWriterBuilderService" );
        }

        stream.Flush();
    }

    public void Initialise(
        string filePath )
    {
        Contract.Requires<ArgumentNullException>( filePath != null );

        fs = File.Open( filePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite );
        stream = new StreamWriter( fs );
        WriteLine("Initialised");
        Initialised = true;
    }

    public bool Initialised { get; private set; }

    #region Dispose Implementation

    ~StreamWriterBuilderService()
    {
        Dispose( false );
        Debug.WriteLine( false, "This StreamWriterBuilderService object was not disposed of" );
    }

    private bool _isDisposed;

    public virtual void Dispose()
    {
        Dispose( true );
        GC.SuppressFinalize( this );
    }

    protected virtual void Dispose(
        bool disposing )
    {
        if ( _isDisposed )
            return;

        if ( disposing && Initialised )
        {
            stream.Dispose();
            fs.Dispose();
            stream = null;
            fs = null;
        }

        _isDisposed = true;
    }

    #endregion Dispose Implementation
}

I am unit testing this with:

    protected readonly string TargetFilePath = Path.GetTempFileName();
    protected const string Header = "Initialised";

    protected override void SetContext()
    {
        SUT = Substitute.For<StreamWriterBuilderService>();
    }

and...

    private string fileContents;
    private const string TestString = @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!£$%^&*()+~@?><|¬";

    protected override void Because()
    {
        base.Because();
        SUT.Initialise( TargetFilePath );
        SUT.WriteLine( TestString );
        SUT.Flush();
        SUT.Dispose();
        fileContents = File.ReadAllText( TargetFilePath );
    }

The trouble I am having is that this:

SUT.Dispose();

does not actually call my Dispose method in my abstract class because it is declared as a virtual method. If I remove the virtual method then the code is played out. However, I need to keep the virtual method there as I need to override elsewhere in my solution...

You should use:

var SUT = Substitute.ForPartsOf<StreamWriterBuilderService>();

This gives you fine control over the specific things you want to substitute. Thus, by default, your Dispose methods won't be substituted.

Alternatively, my recommendation (for this specific scenario) would be to build your own StreamWriterBuilderServiceForTesting class (that inherits from StreamWriterBuilderService ). Because NSubstitute would not be involved, you could define its behaviour however you like.

When you substitute a class like this, the virtual methods are replaced by the substitute. You probably want a partial substitute replacing only Dispose(bool) .

Documentation about partial substitutes

and the second Paragraph here :

For starters, NSubstitute can only work with virtual members of the class, so any non-virtual code in the class will actually execute!

That is, virtual methods will not execute.

I'd create a derived type for testing purposes just to remove the abstract , and then test with that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM