考虑以下测试,
[Theory, MyConventions] public void GetClientExtensionReturnsCorrectValue(BuilderStrategy sut) { var expected = ""; // <--??? the value injected into BuilderStrategy var actual = sut.GetClientExtension(); Assert.Equal(expected, actual); }和我正在使用的自定义属性:
public class MyConventionsAttribute : AutoDataAttribute { public MyConventionsAttribute() : base(new Fixture().Customize(new AutoMoqCustomization())) {} }和SUT:
class BuilderStrategy { private readonly string _clientID; private readonly IDependency _dependency; public void BuilderStrategy(string clientID, IDependency dependency) { _clientID = clientID; _dependency = dependency; } public string GetClientExtension() { return _clientID.Substring(_clientID.LastIndexOf("-") + 1); } }我需要知道在构造函数参数clientID注入了什么值,以便我可以使用它来与GetClientExtension的输出进行比较。 是否可以在将SUT注入测试方法时仍然编写这种测试方式?
Consider the following test,
[Theory, MyConventions] public void GetClientExtensionReturnsCorrectValue(BuilderStrategy sut) { var expected = ""; // <--??? the value injected into BuilderStrategy var actual = sut.GetClientExtension(); Assert.Equal(expected, actual); }and the custom attribute I'm using:
public class MyConventionsAttribute : AutoDataAttribute { public MyConventionsAttribute() : base(new Fixture().Customize(new AutoMoqCustomization())) {} }and the SUT:
class BuilderStrategy { private readonly string _clientID; private readonly IDependency _dependency; public void BuilderStrategy(string clientID, IDependency dependency) { _clientID = clientID; _dependency = dependency; } public string GetClientExtension() { return _clientID.Substring(_clientID.LastIndexOf("-") + 1); } }I need to know what value was injected into the constructor parameter clientID so that I can use it to compare with the output of GetClientExtension. Is it possible to do this while still writing this style of test where the SUT is injected into the test method?
最满意答案
如果将注入的clientID (以及dependency )公开为只读属性,则始终可以查询其值:
public class BuilderStrategy { private readonly string _clientID; private readonly IDependency _dependency; public void BuilderStrategy(string clientID, IDependency dependency) { _clientID = clientID; _dependency = dependency; } public string GetClientExtension() { return _clientID.Substring(_clientID.LastIndexOf("-") + 1); } public string ClientID { get { return _clientID; } } public IDependency Dependency { get { return _dependency; } } }这不会破坏封装,而是称为结构检查 。
通过此更改,您现在可以像这样重写测试:
[Theory, MyConventions] public void GetClientExtensionReturnsCorrectValue(BuilderStrategy sut) { var expected = sut.ClientID.Substring(sut.ClientID.LastIndexOf("-") + 1); var actual = sut.GetClientExtension(); Assert.Equal(expected, actual); }有些人不喜欢在单元测试中复制生产代码,但我宁愿争辩说,如果你遵循测试驱动开发,那么生产代码就会复制测试代码。
无论如何,这是一种称为派生值的技术。 在我看来, 只要它保持1的圈复杂度,我们仍然可以相信这个测试 。 此外,只要重复的代码只出现在两个地方, 三个规则就表明我们应该保持这样。
If you expose the injected clientID (and dependency as well) as read-only properties, you can always query their values:
public class BuilderStrategy { private readonly string _clientID; private readonly IDependency _dependency; public void BuilderStrategy(string clientID, IDependency dependency) { _clientID = clientID; _dependency = dependency; } public string GetClientExtension() { return _clientID.Substring(_clientID.LastIndexOf("-") + 1); } public string ClientID { get { return _clientID; } } public IDependency Dependency { get { return _dependency; } } }This doesn't break encapsulation, but is rather known as Structural Inspection.
With this change, you could now rewrite the test like this:
[Theory, MyConventions] public void GetClientExtensionReturnsCorrectValue(BuilderStrategy sut) { var expected = sut.ClientID.Substring(sut.ClientID.LastIndexOf("-") + 1); var actual = sut.GetClientExtension(); Assert.Equal(expected, actual); }Some people don't like duplicating production code in the unit test, but I would rather argue that if you follow Test-Driven Development, it's the production code that duplicates the test code.
In any case, this is a technique known as Derived Value. In my opinion, as long as it retains a cyclomatic complexity of 1, we can still trust the test. Additionally, as long as the duplicated code only appears in two places, the rule of three suggests that we should keep it like that.
更多推荐
发布评论