Can a particular constructor argument of an injected SUT using Autodata xUnit Theories?

最后都变了- 提交于 2019-12-23 16:31:23

问题


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?


回答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.



来源:https://stackoverflow.com/questions/18238348/can-a-particular-constructor-argument-of-an-injected-sut-using-autodata-xunit-th

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!