我有这个基础(抽象)类:
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
}
我正在对此进行单元测试:
protected readonly string TargetFilePath = Path.GetTempFileName();
protected const string Header = "Initialised";
protected override void SetContext()
{
SUT = Substitute.For<StreamWriterBuilderService>();
}
和...
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 );
}
我遇到的麻烦就是:
SUT.Dispose();
实际上并没有在我的抽象类中调用我的Dispose方法,因为它被声明为虚方法。如果我删除虚拟方法,则代码将被播放。但是,我需要将虚拟方法保留在那里,因为我需要在我的解决方案中覆盖其他地方......
答案 0 :(得分:2)
您应该使用:
has_one
这会让您fine control超过您想要替换的特定内容。 因此,默认情况下,您的var SUT = Substitute.ForPartsOf<StreamWriterBuilderService>();
方法不会被替换。
或者,我的建议(针对此特定方案)将构建您自己的Dispose
类(继承自StreamWriterBuilderServiceForTesting
)。 因为不参与NSubstitute,你可以根据自己的喜好定义它的行为。
答案 1 :(得分:1)
当您substitute
这样的类时,虚拟方法将替换为替换。您可能希望部分替换仅替换Dispose(bool)
。
Documentation about partial substitutes
对于初学者来说,NSubstitute只能使用该类的虚拟成员,因此该类中的任何非虚拟代码都将实际执行!
也就是说,虚拟方法将不执行。
为了测试目的,我创建了一个派生类型,只是为了删除abstract
,然后用它进行测试。