在这个测试中,我预计dummyVar是空的.但是,无论我将OmitAutoProperty设置为什么,它都不是.
这是正确的行为吗?为什么?什么是AutoFixture创建空虚拟人集合的方式?
[Fact]
public void ShouldBeEmpty()
{
var fixture = new Fixture();
fixture.Customize(new AutoMoqCustomization());
fixture.OmitAutoProperties = true;
var dummyVar = fixture.Create<IEnumerable<IComparable>>();
Assert.Empty(dummyVar);
}
Run Code Online (Sandbox Code Playgroud) 我在我的测试中使用 AutoFixture 和 AutoMoqCustomization。
我有一个服务,它是被测系统的依赖项:
ISomeService
{
Task<IEnumerable<int>> Get();
}
Run Code Online (Sandbox Code Playgroud)
我在被测系统内部调用它:
var collection = await _someService.Get(); // collection is empty
Run Code Online (Sandbox Code Playgroud)
我不在乎集合里面有什么,但我需要集合不是空的。我这样做:
_fixture.Freeze<Mock<ISomeService>>()
.Setup(service => service.Get())
.Returns(Task.FromResult(_fixture.CreateMany<int>()));
Run Code Online (Sandbox Code Playgroud)
看起来应该通过自定义来完成。我创建并注册了一个:
public class TaskCollectionCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new FilteringSpecimenBuilder(
new TaskCollectionBuilder(),
new GenericTypeSpecification(typeof(Task<>))));
}
private class TaskCollectionBuilder : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
// never enters here
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是它的 Create 方法从未被输入。任何想法或即用型解决方案?
编辑
添加 GenericTypeSpecification 源
public class GenericTypeSpecification : IRequestSpecification …
Run Code Online (Sandbox Code Playgroud) 我刚刚更改了[RegularExpression]
验证,三分之一的单元测试失败了!
事实证明 AutoFixture 是基于那个正则表达式生成值,这很酷,但它不能理解所有的正则表达式,所以我想提供一个更简单的:
Fixtures.Customize<Details>(c => c.With(d => d.PhoneNumber,
new SpecimenContext(Fixtures).Resolve(
new RegularExpressionRequest(@"[2-9]\d{2}-\d{3}-\d{4}"))));
Run Code Online (Sandbox Code Playgroud)
这最终在对象创建时给了我一个通用的 LINQ 错误(“序列不包含元素。”)。我究竟做错了什么?
或者,有什么办法可以关闭此功能? Customize()
很有帮助,但它阻止我在Build()
不重复所有相同逻辑的情况下使用。(不是吗?)
我需要启用 AutoFixture 来创建具有循环引用的类型实例(来自第三方提供的 API)。为此,我可以删除默认值ThrowingRecursionBehavior
,如下所示:
public class RecursiveObjectCustomization : ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Behaviors.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(b => fixture.Behaviors.Remove(b));
fixture.Behaviors.Add(new OmitOnRecursionBehavior());
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我知道ThrowingRecursionBehavior
当通过属性应用自定义时,这将删除所有类型的 。如何将修改后的行为限制为仅适用于特定类型?
我目前正在使用一个测试框架,该框架是我使用 xUnit、AutoMoq、AutoFixture 和 AutoFixture.XUnit2 组合而成的。我遇到了使用通用签名的模拟方法的问题。
AutoFixture 似乎可以很好地处理通用项目。如果我要求一个CustomeObject<Task<List<Task<string>>>>
或其他一些荒谬的嵌套泛型类型,它似乎会按预期生成它们,一直到最后一个节点。
但是,如果我有这样的界面:
public interface ITestInterface{
T Get<T>();
}
Run Code Online (Sandbox Code Playgroud)
然后尝试从我从 AutoMoq 获得的模拟中调用该方法,它只返回 null。因此,例如:
[Theory]
[MyAutoDaqaAttribute]
public async Task ATest(
Mock<ITestInterface> service
) {
var result = service.Object.Get<string>();
}
Run Code Online (Sandbox Code Playgroud)
在此代码中,结果将为空。这对我来说似乎很奇怪。难道它不应该转到 autofixture 并尝试创建 T 类型的值(即新字符串)吗?看起来 Autofixture 已经表明它可以很好地处理泛型。
或者您是否总是需要手动设置任何签名中具有泛型的模拟方法?
在此示例代码中,我想配置一个Fixture
对象以null
在一半的时间内返回字符串。
void Test()
{
var fixture = new Fixture();
fixture.Customize<string>(x => x.FromFactory(CreateString));
var str1 = fixture.Create<string>();
//error occurs here when string should come back null
var str2 = fixture.Create<string>();
}
bool _createString = false;
string CreateString()
{
_createString = !_createString;
return _createString ? "test" : null;
}
Run Code Online (Sandbox Code Playgroud)
问题是,每当我的工厂返回时null
,我都会得到InvalidOperationException
:
装饰的 ISpecimenBuilder 返回的样本与 System.String 不兼容。
对于我null
在工厂内返回的任何类型,都会发生这种情况。有没有办法配置AutoFixture
返回null
请求的对象?
冻结后是否可以解冻对象类型?
所以如果我有一个使用 DateTime 的对象约会,有没有办法做这样的事情?
var time = fixture.Freeze<DateTime>();
IEnumerable<ClientAppointment> appointments = fixture.CreateMany < ClientAppointment>();
fixture.Unfreeze<ClientAppointment>();
Run Code Online (Sandbox Code Playgroud)
这样我就可以生成注入了不同 DateTime 的新对象?
我试图从某些枚举类型的值集中排除某些枚举值,例如Unknown
和。Uninitialized
我可以看到它Enums
是使用给定类型EnumGenerator
的所有可能Enum
值的集合以循环方式生成的Enum
。
基于该代码,我的第一个想法是构建一个ISpecimenBuilder
检查Type.IsEnum
并执行context.Resolve(request)
直到直到Resolve
返回不在排除列表中的值的对象。
问题是这给了我递归错误。在检查了源代码之后,我明白了原因-如果构建器处理了一个请求,然后Resolve
再次用相同的请求调用另一个,您将陷入无限循环。
但是由于它EnumGenerator
是不可扩展的,而且我无法弄清楚如何拦截构建链,因此我很困惑如何解决此问题。
我正在尝试使用 AutoFixture 创建一个夹具,其中对象的一个属性与另一个属性相关,并且其中一个属性被创建为夹具的一部分。
到目前为止我所拥有的是:
fixture = new Fixture().Customize(new MultipleCustomization());
Object object;
double constant;
object = fixture.Build<Object>()
.With(o => o.PropertyOne, fixture.Create<double>)
.With(o => o.PropertyTwo, constant * o.PropertyOne)
.Create());
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为“当前上下文中不存在名称 'o'”,这是有道理的。
作为夹具创建的一部分,有没有办法做到这一点?
我的情况有点复杂,因为我实际上是在生成一个列表,所以代码看起来像:
fixture = new Fixture().Customize(new MultipleCustomization());
List<Object> objectListFixture;
double constant;
objectListFixture.AddRange(
fixture.Build<Object>()
.With(o => o.PropertyOne, fixture.Create<double>)
.With(o => o.PropertyTwo, constant * o.PropertyOne)
.CreateMany());
Run Code Online (Sandbox Code Playgroud)
如果可能的话,我真的很想避免 for 循环。
我正在尝试使用 mstest 为 .net Core 3 Web API 构建单元测试。
我也在使用:
NotFound()
当没有找到啤酒时,这个单元测试应该返回一个响应。
private IFixture _fixture;
private BeerController _beerController;
private Mock<IBeerService> _mockBeerService;
[TestInitialize]
public void Initialize()
{
_fixture = new Fixture().Customize(new AutoMoqCustomization());
_mockBeerService = _fixture.Freeze<Mock<IBeerService>>();
_beerController = _fixture.Create<BeerController>();
}
[TestMethod]
public async Task WhenCallGetBeerWithoutMatchReturnNotFound404()
{
//Arrange
int beerId = _fixture.Create<int>();
_mockBeerService.Setup(x => x.GetBeer(It.IsAny<int>())).Returns((Task<Beer>)null);
//Act
var actionResult = await _beerController.Get(beerId);
//Assert
Assert.IsInstanceOfType(actionResult.Result, typeof(NotFoundResult));
}
Run Code Online (Sandbox Code Playgroud)
这就是我要测试的功能:
[HttpGet("{beerId:int}")]
public async Task<ActionResult<beer>> Get(int beerId)
{
try
{
var beer = await _beerService.Getbeer(beerId); …
Run Code Online (Sandbox Code Playgroud)