.NET核心使用Xunit + Autofixture + Moq编写更好的单元测试 [英] .NET core write better unit tests with Xunit + Autofixture + Moq
问题描述
在用于单元测试的.NET Core中,我正在使用Xunit,Moq和Autofixture.但是,即使有了它们,我仍然发现我的单元测试变得复杂且耗时.
In .NET Core for unit testing, I'm using Xunit, Moq, and Autofixture. But even with them, I see that my unit tests become complicated and take time.
也许有人可以告诉我是否有任何方法可以使此测试更小?
Maybe someone could tell me if there are any ways to make this test smaller?
[Fact]
public async Task Verify_NotAuthorised_NoServiceSendInvoked()
{
// Arrange
var fixture = new Fixture()
.Customize(new AutoMoqCustomization());
var sut = fixture.Create<VerificationService>();
var mockApiBuilder = fixture.Freeze<Mock<IApiEntityBuilder>>();
//init mocked mockSendServiceOne, so later I could check if it was invoked or not
var mockSendServiceOne = fixture.Freeze<Mock<ISendServiceOne>>();
mockApiBuilder.Setup(x => x.Verification(It.IsAny<string>(), It.IsAny<string>()))
.Returns(fixture.Create<VerificationEntity>());
var call = fixture.Freeze<Mock<ISendServiceTwo>>();
call.Setup(x => x.IsSuccessful()).Returns(false);
// Act
await sut.Verify(fixture.Create<string>(), fixture.Create<string>());
// Assert
mockSendServiceOne.Verify(x => x.Call(It.IsAny<SendServiceOneEntity>()), Times.Never);
}
测试方法本身
public async Task<CreatedEntity> Verify(string dataOne, string dataTwo)
{
await _someCaller.Call(_apiEntityBuilder.Verification(dataOne, dataTwo));
_someCaller.CreatePayment();
if (!_someCaller.IsSuccessful()) return _someCaller.CreatedEntity;
await mockSendServiceOne.Call(_apiEntityBuilder.Call(_someCaller.CreatedEntity.SpecificData));
return _someCaller.CreatedEntity;
}
在这里,我正在测试isSuccessful()是否返回fasle,然后不应该调用mockSendServiceOne.Call.
Here I am testing if isSuccessful() returns fasle then no mockSendServiceOne.Call should be invoked.
有人可以给我一些有关如何编写更好的单元测试的反馈.因为只需要对代码进行少量检查,所以我不得不编写大量代码对其进行测试.
Could someone give me some feedback on how to write a better unit tests. Because only for this small check of code I had to write a lot of code to test it.
推荐答案
您可以使用自动数据理论.(链接到Mark Seeman的一篇很棒的帖子,介绍了这种确切情况).
You can use AutoData Theories. (Links to a great post by Mark Seeman about this exact situation).
简而言之,AutoFixture具有一个名为 AutoData
的内置属性,您可以从中继承该属性,然后使用AutoMoqCustomization自定义灯具.
In short AutoFixture has a built in attribute called AutoData
which you can inherit from and then customize the fixture with the AutoMoqCustomization.
您使用此属性装饰测试方法([Theory]),现在自动固定将自动生成您为测试方法指定的任何参数.
You decorate your testmethod ([Theory]) with this attribute, and now autofixture automagically will generate any parameter you specify for your testmethod.
当您使用 Freeze()
方法生成项目时,请将 [Frozen]
属性放在参数前面.
When you would use the Freeze()
method to generate an item, you put the [Frozen]
attribute in front of the parameter.
以下是如何执行此操作的示例:
Here is an example of how to do it:
public class TheTests
{
[Theory]
[AutoDomainData]
public void Verify_WhatWeWannaTest_CallsTheMethodOnTheDependency([Frozen] Mock<ITheDependency> dependency, WhatWeWannaTest sut)
{
// Act
sut.CallTheDependency();
// Assert
dependency.Verify(x => x.TheMethod());
}
}
// Create a AutoData attribute customized with Moq
public class AutoDomainDataAttribute : AutoDataAttribute
{
public static IFixture FixtureFactory()
{
var f = new Fixture();
// I like members of interfaces to be configured, so i set it her
f.Customize(new AutoMoqCustomization { ConfigureMembers = true });
return f;
}
public AutoDomainDataAttribute() : base(FixtureFactory) { }
}
// Simple class we can test
public class WhatWeWannaTest
{
private readonly ITheDependency _theDependency;
public WhatWeWannaTest(ITheDependency theDependency) { _theDependency = theDependency; }
public void CallTheDependency()
{
_theDependency.TheMethod();
}
}
// Simple dependency for WhatWeWannaTest
public interface ITheDependency
{
int TheMethod();
}
这篇关于.NET核心使用Xunit + Autofixture + Moq编写更好的单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!