{C#-05C} 单测.复合方法

2020-10-01  本文已影响0人  码农猫爸
背景
代码例
namespace Presenters
{
    public class SchemaEnviroment
    {
        // 输出(需单测)
        // 外部环境上再加工
        // 虚方法,本类作为外部环境时,可替换为模拟值,下同。
        public virtual string Position =>
            Server.StartsWith("127.") ||
            Server == "localhost" ? "local" : "net";
        // ...

        // 输出(不单测)
        // 直接调用外部模块的方法或属性,即过桥
        public virtual string[] Schemas
            => new KD.SchemaQuery().GetSchemas(true)
                .Keys.ToArray();
        // ...

        // 输入
        // 内生受保护的虚方法,无接口,减少注入层级
        // 也可换作接口注入,但增加代码和理解的复杂度
        protected virtual string Server
            => ConfigIO.Server;
        // ...
    }
}
namespace Tests
{
    public class SchemaEnviromentTests
    {
        Mock<SchemaEnviroment> mock = new Mock<SchemaEnviroment>();

        [Theory(DisplayName = "位置")]
        [InlineData("127.0.0.1", "local")]
        [InlineData("localhost", "local")]
        [InlineData("128.0.0.1", "net")]
        public void Position_ReturnsTrue(string server, string expected)
        {
            Reset(server);
            string actual = mock.Object.Position;

            Assert.Equal(expected, actual);
        }
        // ...

        private void Reset(string server = "127.0.0.1")
        {
             mock.CallBase = true;
             mock.Protected()
                .Setup<string>("Server")
                .Returns(server);
            // ...
        }
    }
}
namespace Presenters
{
    public class SchemaSuggestion
    {
        private SchemaEnviroment env;

        public SchemaSuggestion(SchemaEnviroment env)
        {
            this.env = env;
        }

        public virtual string ToClear(string input)
            => input == "" ? null : "[清空]";
        // ...        
    }
}
namespace Tests
{
    public class SchemaSuggestionTests
    {
        Mock<SchemaSuggestion> mock;

        [Theory(DisplayName = "待清空")]
        [InlineData("", null)]
        [InlineData("any", "[清空]")]
        public void ToClear_ReturnsTrue(string input, string expected)
        {
            Reset();
            string actual = mock.Object.ToClear(input);

            Assert.Equal(expected, actual);
        }
        // ...

        private void Reset(bool isDev = true)
        {
            Mock<SchemaEnviroment> env = new Mock<SchemaEnviroment>();
            env.Setup(x => x.Position).Returns("local");
            // ..

            mock = new Mock<SchemaSuggestion>(env.Object);
            mock.CallBase = true; // 使用原函数,不替换
        }
    }
}
namespace Presenters
{
    public class SchemaName
    {
        private SchemaSuggestion suggestion;

        public SchemaName(SchemaSuggestion suggestion)
        {
            this.suggestion = suggestion;
        }

        public List<string> Suggest(string input)
        {
            var result = new List<string>
            {
                suggestion.ToClear(input),
                // ...
            };

            result.AddRange(suggestion.ToFilter(input));

            return result.FindAll(name => name != null);
        }
    }
}
namespace Tests
{
    public class SchemaNameTests
    {
        Mock<SchemaName> mock;

        [Fact(DisplayName = "建议")]
        public void Suggest_ReturnsTrue()
        {
            var expected = SuggestStub();

            Reset();
            var actual = mock.Object.Suggest(""); // 待清空=null

            Assert.Equal(expected, actual);
        }

        private List<string> SuggestStub()
            => new List<string> {  // ...  };

        private void Reset()
        {
            Mock<SchemaSuggestion> suggestion = new Mock<SchemaSuggestion>(null);
            suggestion
                .Setup(x => x.ToClear(It.IsAny<string>()))
                .Returns((string)null);
            // ...

            mock = new Mock<SchemaName>(suggestion.Object);
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读