简体   繁体   English

使用nSubstitute时未调用抽象的Dispose方法

[英]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. 实际上没有在抽象类中调用我的Dispose方法,因为它被声明为虚拟方法。 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. 因此,默认情况下,不会替换您的Dispose方法。

Alternatively, my recommendation (for this specific scenario) would be to build your own StreamWriterBuilderServiceForTesting class (that inherits from StreamWriterBuilderService ). 另外,我的建议(针对此特定方案)将是构建您自己的StreamWriterBuilderServiceForTesting类(该类继承自StreamWriterBuilderService )。 Because NSubstitute would not be involved, you could define its behaviour however you like. 因为不涉及NSubstitute,所以您可以根据自己的喜好定义其行为。

When you substitute a class like this, the virtual methods are replaced by the substitute. 当您substitute的类时, 虚拟方法将被替换。 You probably want a partial substitute replacing only Dispose(bool) . 您可能只想部分替换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! 对于初学者来说,NSubstitute只能与该类的虚拟成员一起使用,因此该类中的任何非虚拟代码都将实际执行!

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. 我将创建派生类型以进行测试,以删除abstract ,然后进行测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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