gpt4 book ai didi

c# - Autofixture 模拟接口(interface)以返回随机结果用于测试目的

转载 作者:太空狗 更新时间:2023-10-29 21:50:31 27 4
gpt4 key购买 nike

问题

我有一个相当大的应用程序,它使用了很多其他服务。对于测试场景,我不希望我的单元测试依赖第三方系统,所以我想用假货或模拟或其他任何东西替换服务。

我已经完成了大部分艰苦的工作,并用 IService 替换了具体服务。具体服务与 DI 框架连接

现在我想用随机生成的假货替换它们。

代码

示例服务接口(interface):

public interface ISimpleService
{
int Fizz(int input);

string Buzz(string input);
}

实例服务工厂接口(interface):

public interface ISimpleServiceFactory
{
ISimpleService Create();
}

实现尽可能简单

public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var service = fixture.Create<ISimpleService>();

var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}

这显示了我基本上想要的。我只希望 autofixture 为我创建一些动态代理对象,使用返回接口(interface)中指定类型的随机值的方法...

请注意,我在这里使用了 AutoMoq,因为默认情况下 Fixture 不想从接口(interface)创建对象,但我也尝试过其他框架:FakeItEasy、AutoRhinoMock

解决方法

通过手动设置所有内容来实现这种工作方式

public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var serviceMock = fixture.Create<Mock<ISimpleService>>();

// These two lines below cause the magic now
serviceMock.Setup(x => x.Fizz(It.IsAny<int>())).Returns(fixture.Create<int>());
serviceMock.Setup(x => x.Buzz(It.IsAny<string>())).Returns(fixture.Create<string>());

var service = serviceMock.Object;
var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}

这确实给了我想要的结果:带有随机 int 的 fizzResult,带有随机字符串的 buzzResult(默认为 guid)然而,这只是一个小例子,我的实际服务引用要大得多,有多达 100 种方法...(它们是外部 soap 服务等,没办法)我不想手动设置所有内容,如果有一个通用的解决方案,那就太好了......

一种通过手动设置一切来工作的工厂实现

因此,您可能已经注意到,我还发布了一个 ISimpleServiceFactory 接口(interface)。这类似于实际情况,因为实际的具体 ISimpleService 需要大量配置。所以,如果我们使用那种可行的解决方案,我们会得出这样的结论:

public static void Main(string[] args)
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var serviceFactoryMock = fixture.Create<Mock<ISimpleServiceFactory>>();

var serviceMockDelegate = new Func<ISimpleService>(() =>
{
var serviceMock = fixture.Create<Mock<ISimpleService>>();
serviceMock.Setup(x => x.Fizz(It.IsAny<int>())).Returns(fixture.Create<int>());
serviceMock.Setup(x => x.Buzz(It.IsAny<string>())).Returns(fixture.Create<string>());

return serviceMock.Object;
});

serviceFactoryMock.Setup(x => x.Create()).Returns(serviceMockDelegate);
var service = serviceFactoryMock.Object.Create();

var fizzResult = service.Fizz(42);
var buzzResult = service.Buzz("I'd like something random...");
}

这看起来有点乱,而且这是一个非常小的界面。实际服务有很多层次,有数百种方法。

对于我的代码中需要特定条件的方法,我显然仍会手动设置这些条件,但默认情况下其他一切都应该是随机值。生成大量随机对象也允许进行一些模糊测试

有没有一种方法可以自动生成随机对象而无需所有这些手动设置?

最佳答案

您不需要工厂,也不需要在接口(interface)中设置每个方法,如果我理解正确的话,您只是想使用 Fixture 创建一个为每个方法返回随机值的代理您调用该代理。不要使用 AutoMoqCustomization,而是使用 AutoConfiguredMoqCustomization。这一切都在名为 Fixture.AutoMoq 的 nuget 包中。

class Program
{
static void Main(string[] args)
{
}
}

[TestFixture]
public class program
{
[Test]
public void some_test()
{
var fixture = new Fixture();
fixture.Customize(new AutoConfiguredMoqCustomization());

var simpleServices = fixture.CreateMany<ISimpleService>();

foreach (var simpleService in simpleServices)
{
string randomString = simpleService.Buzz("hello");
int randomInt = simpleService.Fizz(15);
}
}
}

public interface ISimpleService
{
int Fizz(int input);

string Buzz(string input);
}

关于c# - Autofixture 模拟接口(interface)以返回随机结果用于测试目的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19146578/

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