轻松指定单个构造函数参数的值?

时间:2015-02-05 17:13:40

标签: c# autofixture

在Autofixture中是否有一些简单的方法可以使用它的构造函数来创建一个对象,但硬编码/指定用于构造函数中单个参数的值?

我看到这可以通过属性完成,使用类似:

fixture.Build<MyObj>().With(x=x.Val,"hard coded value").Create()

1 个答案:

答案 0 :(得分:11)

从评论中关于这个问题的讨论:

  

我经常想要新建一个对象,但我只关心一个参数。也许参数值驱动某种计算或转换。我希望值本身是随机的,但测试需要知道选择了什么随机值。

假设这是潜在的问题,我将尝试解决这个问题。

询问对象

最简单的解决方案是在AutoFixture创建后简单地询问对象的值:

var fixture = new Fixture();
var mc = fixture.Create<MyClass>();
var specialValue = mc.SpecialValue;
// Do something with specialValue...

如果您只需要了解特殊值是什么,但是您不需要它具有特定值,则可以使用此技术。

这显然要求您将构造函数参数中的值公开为(只读)属性,但是a good idea to do anyway

创建后分配值

如果您需要参数具有特定值,则可以在创建后分配:

var fixture = new Fixture();
var mc = fixture.Create<MyClass>();
mc.SpecialValue = "Some really special value";

这要求您将值作为可写属性提供。虽然我个人并不是这方面的忠实粉丝,因为这会使对象变得可变,但很多人已经按照这种方式设计了他们的对象,如果是这样的话,为什么不利用它呢?

创建后使用复制和更新

如果您希望对象不可变,您仍然可以使用上述技术的变体。在F#中,您可以使用所谓的copy and update expressions来实现相同的目标。在F#中,它类似于:

let fixture = Fixture ()
let mc = {
    fixture.Create<MyRecord> ()
    with SpecialValue = "Some special value!" }

您可以通过提供类复制和更新方法在C#中进行模拟,这样您就可以编写如下内容:

var fixture = new Fixture();
var mc = fixture
    .Create<MyClass>()
    .WithSpecialValue("Some really special value");

这是我在C#代码中一直使用的技术。 AutoFixture有an idiomatic assertion to test such copy and update methods

为参数注入值

如果您可以为特定构造函数参数注入固定值,则可以使用AutoFixture内核的构建块执行此操作。该测试演示了如何:

[Fact]
public void CustomizeParameter()
{
    var fixture = new Fixture();
    fixture.Customizations.Add(
        new FilteringSpecimenBuilder(
            new FixedBuilder("Ploeh"),
            new ParameterSpecification(
                typeof(string),
                "specialValue")));

    var actual = fixture.Create<MyClass>();

    Assert.Equal("Ploeh", actual.SpecialValue);
}

然而,这导致总是的参数是&#34; Ploeh&#34;对于那个fixture实例。它也是重构 - 不安全的,因为它基于一个引用参数名称的字符串。