背景
代码例
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);
}
}
}
网友评论