可以使用Autodata xUnit Theories注入SUT的特定构造函数参数吗?(Can a particular constructor argument of an injected SUT

编程入门 行业动态 更新时间:2024-10-20 05:48:48
可以使用Autodata xUnit Theories注入SUT的特定构造函数参数吗?(Can a particular constructor argument of an injected SUT using Autodata xUnit Theories?)

考虑以下测试,

[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.

更多推荐

本文发布于:2023-08-05 07:58:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1428913.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:可以使用   函数   参数   xUnit   SUT

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!