C# 这是嘲笑还是存根?

C# 这是嘲笑还是存根?,c#,unit-testing,c#-4.0,dependency-injection,moq,C#,Unit Testing,C# 4.0,Dependency Injection,Moq,我有下面的方法要测试,我已经编写了两个测试,测试抛出异常的场景,我想知道哪个是正确的 namespace JimBob.CsvImporter.Entity { public interface IIOManager { Stream OpenFile(string path); TextReader ReturnReader(string path); } public class IOManager : IIOManag

我有下面的方法要测试,我已经编写了两个测试,测试抛出异常的场景,我想知道哪个是正确的

namespace JimBob.CsvImporter.Entity
{

    public interface IIOManager
    {
        Stream OpenFile(string path);

        TextReader ReturnReader(string path);
    }


    public class IOManager : IIOManager
    {
        public Stream OpenFile(string path)
        {
            return File.Open(path, FileMode.Open);
        }

        public TextReader ReturnReader(string filePath)
        {
            return new StreamReader(filePath);
        }
    }


public class EntityVerification
{

    private IIOManager _iomgr;

    public EntityVerification(IIOManager ioManager)
    {
        this._iomgr = ioManager;
    }

    ...

    /// <summary>
    /// Ensures user can open file.
    /// </summary>
    /// <param name="errorMessageList">A running list of all errors encountered.</param>
    public void ValidateAccessToFile(string filePath, List<string> errorMessageList)
    {
        try
        {
            using (FileStream fs = (FileStream)_iomgr.OpenFile(filePath))
            {
                if (fs.CanRead && fs.CanWrite) { }
                else
                {
                    errorMessageList.Add("Can not read/write to the specified file.");
                }
            }
        }
        catch (Exception e)
        {
            errorMessageList.Add(e.Message);
        }
    }
名称空间JimBob.CsvImporter.Entity
{
公共接口管理器
{
流OpenFile(字符串路径);
TextReader ReturnReader(字符串路径);
}
公共类IOManager:IIOManager
{
公共流OpenFile(字符串路径)
{
返回File.Open(路径,FileMode.Open);
}
公共文本读取器ReturnReader(字符串文件路径)
{
返回新的StreamReader(文件路径);
}
}
公共类实体验证
{
私人管理人(iomgr);
公共实体验证(IIOManager ioManager)
{
这个。_iomgr=ioManager;
}
...
/// 
///确保用户可以打开文件。
/// 
///遇到的所有错误的运行列表。
public void ValidateAccessToFile(字符串文件路径,列表错误消息列表)
{
尝试
{
使用(FileStream fs=(FileStream)\u iomgr.OpenFile(filePath))
{
如果(fs.CanRead&&fs.CanWrite){}
其他的
{
errorMessageList.Add(“无法读取/写入指定文件”);
}
}
}
捕获(例外e)
{
errorMessageList.Add(e.Message);
}
}
测试:

    [Test]
    public void ValidateAccessToFile_CanReadWriteToFile_ThrowException()
    {
        List<String> errorMessageList = new List<string>();
        StubService stub = new StubService();
        EntityVerification testObject = new EntityVerification(stub);
        testObject.ValidateAccessToFile("ergesrg", errorMessageList);
        Assert.AreEqual(errorMessageList.Count, 0);
    }

    [Test]
    public void ValidateAccessToFile_CanReadWriteToFile_ThrowsException()
    {
        Mock<IIOManager> mock = new Mock<IIOManager>();
        mock.Setup(x => x.ReturnReader(It.IsAny<string>())).Throws(new InvalidOperation("throw baby."));
        EntityVerification testObject = new EntityVerification(mock.Object);
        List<String> errorMessageList = new List<string>();
        testObject.ValidateAccessToFile("blabla.txt", errorMessageList);
        Assert.AreEqual(errorMessageList.Count, 0);
    }



    public class StubService : IIOManager
    {
        public Exception ex;
        public Stream OpenFile(String path)
        {
            throw ex;
        }
    }
[测试]
public void ValidateAccessToFile\可以通过异常()读写文件
{
List errorMessageList=新建列表();
StubService stub=新StubService();
EntityVerificationTestObject=新的EntityVerification(存根);
ValidateAccessToFile(“ergesrg”,errorMessageList);
Assert.AreEqual(errorMessageList.Count,0);
}
[测试]
public void ValidateAccessToFile\可以通过异常()读写文件
{
Mock Mock=新Mock();
mock.Setup(x=>x.ReturnReader(It.IsAny()).Throws(新的无效操作(“throw baby”));
EntityVerificationTestObject=新的EntityVerification(mock.Object);
List errorMessageList=新建列表();
ValidateAccessToFile(“blabla.txt”,errorMessageList);
Assert.AreEqual(errorMessageList.Count,0);
}
公共类StubService:IIOManager
{
公共例外;
公共流OpenFile(字符串路径)
{
掷骰子;
}
}
这两个测试都只是检查一个局部变量,在本例中是errorMessageList,它包含一些东西,所以我不确定应该使用哪个

如有任何意见,将不胜感激


首先谢谢你,你不应该检查一下你是否在列表中添加了错误信息吗

Assert.AreEqual(errorMessageList.Count, 1);

第二,尽管第二个类不那么冗长,而且可读性更好(因为您不需要实现另一个类),这没关系-这两个测试都是实现同一目标的有效方法。只需选择一个,然后继续下一个功能…

第二个测试看起来更好。我认为您可以使用
IIOManager
使用其他方法。您应该维护第一个测试(更新存根),但对第二个测试不做任何操作


关于
IOManager
FileSystem
-看起来更合适的类名

“我认为IIOManager还有其他方法,您应该维护第一个测试(更新存根),但对第二个测试不做任何操作。”对不起,我不明白。你能详细说明一下吗。IIOManager-is接口,所以你的存根取决于接口。在IIOManager中进行任何更改后,你必须更新存根(例如添加另一个方法)。Mock(第二次测试)不依赖于接口实现。因此,第二个测试比第1个测试更容易维护。我不确定为什么我不应该检查它是否添加了消息。我没有重新引发异常,所以我需要检查它是否向errorMessageList添加了一些内容,以便我可以确定是否可以继续程序的下一阶段。是的,so检查列表是否包含一条消息,而不是零…或使用
Assert.that(errorMessageList,Is.not.Empty);
@SilverNinja,感谢您的编辑。