gpt4 book ai didi

c# - 如何使用 NSubstitute 和/或 AutoFixture 测试具体类

转载 作者:行者123 更新时间:2023-11-30 13:55:58 32 4
gpt4 key购买 nike

我希望通过使用 AutoFixture 和 NSubstitue,我可以充分利用各自提供的功能。我单独使用 NSubstitute 取得了一些成功,但我完全不知道如何将它与 AutoFixture 结合使用。

我下面的代码显示了我试图完成的一组事情,但我在这里的主要目标是完成以下场景:测试方法的功能。

  1. 我希望使用随机值调用构造函数(可能除了一个 - 请阅读第 2 点)。
  2. 无论是在构造期间还是之后,我都想更改属性 -Data 的值。
  3. 接下来调用Execute并确认结果

我正在尝试进行的测试是:“should_run_GetCommand_with_provided_property_value”

对说明如何使用 NSubstitue 和 AutFixture 的文章的任何帮助或引用都很棒。

示例代码:

using FluentAssertions;
using NSubstitute;
using Ploeh.AutoFixture;
using Ploeh.AutoFixture.AutoNSubstitute;
using Xunit;

namespace RemotePlus.Test
{
public class SimpleTest
{
[Fact]
public void should_set_property_to_sepecified_value()
{
var sut = Substitute.For<ISimple>();
sut.Data.Returns("1,2");

sut.Data.Should().Be("1,2");
}

[Fact]
public void should_run_GetCommand_with_provided_property_value()
{
/* TODO:
* How do I create a constructor with AutoFixture and/or NSubstitute such that:
* 1. With completely random values.
* 2. With one or more values specified.
* 3. Constructor that has FileInfo as one of the objects.
*
* After creating the constructor:
* 1. Specify the value for what a property value should be - ex: sut.Data.Returns("1,2");
* 2. Call "Execute" and verify the result for "Command"
*
*/
// Arrange
var fixture = new Fixture().Customize(new AutoNSubstituteCustomization());
// var sut = fixture.Build<Simple>().Create(); // Not sure if I need Build or Freeze
var sut = fixture.Freeze<ISimple>(); // Note: I am using a Interface here, but would like to test the Concrete class
sut.Data.Returns("1,2");

// Act
sut.Execute();

// Assert (combining multiple asserts just till I understand how to use NSubstitue and AutoFixture properly
// sut.Received().Execute();
sut.Data.Should().Be("1,2");
sut.Command.Should().Be("1,2,abc");
// Fails with : FluentAssertions.Execution.AssertionFailedExceptionExpected string to be "1,2,abc" with a length of 7, but "" has a length of 0.

}
}

public class Simple : ISimple
{

// TODO: Would like to make this private and use the static call to get an instance
public Simple(string inputFile, string data)
{
InputFile = inputFile;
Data = data;

// TODO: Would like to call execute here, but not sure how it will work with testing.
}

// TODO: Would like to make this private
public void Execute()
{
GetCommand();
// Other private methods
}

private void GetCommand()
{
Command = Data + ",abc";
}

public string InputFile { get; private set; }
public string Data { get; private set; }

public string Command { get; private set; }


// Using this, so that if I need I can easliy switch to a different concrete class
public ISimple GetNewInstance(string inputFile, string data)
{
return new Simple(inputFile, data);
}

}

public interface ISimple
{
string InputFile { get; } // TODO: Would like to use FileInfo instead, but haven't figured out how to test. Get an error of FileNot found through AutoFixture
string Data { get; }
string Command { get; }

void Execute();
}
}

最佳答案

我并没有真正使用过 AutoFixture,但根据一些阅读和一些反复试验,我认为您误解了它会为您做什么和不会为您做什么。在基本层面上,它会让你创建一个对象图,根据对象构造函数(可能还有属性,但我没有研究过)为你填充值。

使用 NSubstitute 集成不会使您的类的所有成员成为 NSubstitute 实例。相反,它赋予夹具框架创建抽象/接口(interface)类型作为替代品的能力。

查看您要创建的类,构造函数采用两个 string 参数。这些都不是抽象类型或接口(interface),因此 AutoFixture 只会为您生成一些值并将它们传递进来。这是 AutoFixture 的默认行为,并且基于 answer。 @Mark Seemann 在评论中链接到这是设计使然。他在那里提出了各种变通办法,如果对您来说真的很重要,您可以实现这些变通办法,我不会在这里重复。

您在评论中表示您确实想将 FileInfo 传递到您的构造函数中。这导致 AutoFixture 出现问题,因为它的构造函数接受一个字符串,因此 AutoFixture 向它提供一个随机生成的字符串,这是一个不存在的文件,所以你会得到一个错误。尝试隔离以进行测试似乎是一件好事,因此 NSubstitute 可能对它有用。考虑到这一点,我建议您可能想要重写您的类并测试如下内容:

首先为 FileInfo 类创建一个包装器(注意,根据您正在做的事情,您可能想要实际包装您想要的 FileInfo 中的方法,而不是将其作为属性公开这样您实际上就可以将自己与文件系统隔离开来,但目前这样做就可以了):

public interface IFileWrapper {
FileInfo File { get; set; }
}

在您的 ISimple 界面中使用它而不是 string(注意我已经删除了 Execute,因为您似乎不需要它):

public interface ISimple {
IFileWrapper InputFile { get; }
string Data { get; }
string Command { get; }
}

编写 Simple 来实现接口(interface)(我还没有解决你的私有(private)构造函数问题,或者你在构造函数中调用 Execute ):

public class Simple : ISimple {

public Simple(IFileWrapper inputFile, string data) {
InputFile = inputFile;
Data = data;
}

public void Execute() {
GetCommand();
// Other private methods
}

private void GetCommand() {
Command = Data + ",abc";
}

public IFileWrapper InputFile { get; private set; }
public string Data { get; private set; }

public string Command { get; private set; }
}

然后是测试:

public void should_run_GetCommand_with_provided_property_value() {
// Arrange
var fixture = new Fixture().Customize(new AutoNSubstituteCustomization());

// create and inject an instances of the IFileWrapper class so that we
// can setup expectations
var fileWrapperMock = fixture.Freeze<IFileWrapper>();

// Setup expectations on the Substitute. Note, this isn't needed for
// this test, since the sut doesn't actually use inputFile, but I've
// included it to show how it works...
fileWrapperMock.File.Returns(new FileInfo(@"c:\pagefile.sys"));


// Create the sut. fileWrapperMock will be injected as the inputFile
// since it is an interface, a random string will go into data
var sut = fixture.Create<Simple>();

// Act
sut.Execute();


// Assert - Check that sut.Command has been updated as expected
Assert.AreEqual(sut.Data + ",abc", sut.Command);

// You could also test the substitute is don't what you're expecting
Assert.AreEqual("pagefile.sys", sut.InputFile.File.Name);
}

我没有使用上面的流利断言,但你应该能够翻译...

关于c# - 如何使用 NSubstitute 和/或 AutoFixture 测试具体类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30812268/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com