使用接口在 Moq 中模拟泛型方法
Mocking generic methods in Moq with interface
我正在尝试为以下通用接口设置最小起订量,但出现异常
public interface IReadAccess<TEntity>
{
Task<IEnumerable<TEntity>> GetAll();
}
var m = new Mock<IReadAccess<Foo>>(MockBehavior.Strict);
m.Setup(p => p.GetAll()).ReturnsAsync(new List<Foo>());
m.VerifyAll();
出现以下异常
Moq.MockException
HResult=0x80131500
Message=The following setups on mock
'Mock<EPIC.CrossCutting.Interfaces.DAL.Framework.IReadAccess<EPIC.CrossCutting.DTOs.Data.Announcement.AnnouncementCrosscutDTO>:00000002>'
were not matched:
IReadAccess<AnnouncementCrosscutDTO> p => p.GetAll()
Source=Moq
StackTrace:
at Moq.Mock.VerifyAll()
at EPIC.Tests.Business.Rules.Announcements.AnnouncementPlanning.CrosscutsProgrammaticActivitiesValidationRuleServiceTests.<ExecuteSuccessTest>d__5.MoveNext()
in D:\dev\main\Tests\EPIC.Tests.Business.Rules\Announcements\AnnouncementPlanning\CrosscutsProgrammaticActivitiesValidationRuleServiceTests.cs:line 108
您的测试正确地失败了,因为您试图验证是否调用了 GetAll(),即使您实际上并没有调用它。
如果您在测试中或正在测试的代码中调用该方法,它将通过。
[Fact]
public async Task Test1()
{
var m = new Mock<IReadAccess<Foo>>(MockBehavior.Strict);
m.Setup(p => p.GetAll()).ReturnsAsync(new List<Foo>());
var result = await m.Object.GetAll();
m.VerifyAll();
}
线索在您的错误消息中:
Message=The following setups on mock .... were not matched:
IReadAccess p => p.GetAll()
谢谢康奈尔,这是预期的工作,但我有类似的方法
public interface IReadAccess<TEntity>
{
Task<IEnumerable<TEntity>> GetAll();
Task<IEnumerable<TEntity>> Find(FormattableString whereClause, object whereClauseObject);
}
并尝试设置
var m = new Mock<IReadAccess<Foo>>(MockBehavior.Strict);
m.Setup(x => x.Find($"ID = @ID", new { ID = 5 })).ReturnsAsync(new List<Foo>());
var result = await m.Object.Find($"ID= @ID", new { ID = 5 });
m.VerifyAll();
在对现有代码进行一些更改后,现在设置工作正常,但在从测试调用时实际服务出现错误,更新代码
var test = new Test {ID = 5};
object whereClause = new { ID = test.ID };
FormattableString formattableString = $"ID = @ID";
m.Setup(x => x.Find(formattableString, whereClause)).ReturnsAsync(new List<Foo>());
var ruleServiceOutput = await this.testValidationRuleService.ExecuteAsync(test);
实际代码
public async Task<IRuleServiceOutput<bool>> ExecuteAsync(Test test)
{
var errors = new List<string>();
object whereClause = new { ID = test.ID };
FormattableString formattableString = $"ID = @ID";
var output = (await m.Find(formattableString, whereClause)).ToArray();
return new RuleServiceOutput<bool>(output.Errors.IsEmpty(), output.Errors);
}
'IReadAccess`1.Find(ID = @ID, { ID = 5 }) 调用失败,模拟行为严格。
模拟上的所有调用都必须具有相应的设置。'
设置 MockBehavior.Default 后一切正常:)
我正在尝试为以下通用接口设置最小起订量,但出现异常
public interface IReadAccess<TEntity>
{
Task<IEnumerable<TEntity>> GetAll();
}
var m = new Mock<IReadAccess<Foo>>(MockBehavior.Strict);
m.Setup(p => p.GetAll()).ReturnsAsync(new List<Foo>());
m.VerifyAll();
出现以下异常
Moq.MockException
HResult=0x80131500
Message=The following setups on mock
'Mock<EPIC.CrossCutting.Interfaces.DAL.Framework.IReadAccess<EPIC.CrossCutting.DTOs.Data.Announcement.AnnouncementCrosscutDTO>:00000002>'
were not matched:
IReadAccess<AnnouncementCrosscutDTO> p => p.GetAll()
Source=Moq
StackTrace:
at Moq.Mock.VerifyAll()
at EPIC.Tests.Business.Rules.Announcements.AnnouncementPlanning.CrosscutsProgrammaticActivitiesValidationRuleServiceTests.<ExecuteSuccessTest>d__5.MoveNext()
in D:\dev\main\Tests\EPIC.Tests.Business.Rules\Announcements\AnnouncementPlanning\CrosscutsProgrammaticActivitiesValidationRuleServiceTests.cs:line 108
您的测试正确地失败了,因为您试图验证是否调用了 GetAll(),即使您实际上并没有调用它。
如果您在测试中或正在测试的代码中调用该方法,它将通过。
[Fact]
public async Task Test1()
{
var m = new Mock<IReadAccess<Foo>>(MockBehavior.Strict);
m.Setup(p => p.GetAll()).ReturnsAsync(new List<Foo>());
var result = await m.Object.GetAll();
m.VerifyAll();
}
线索在您的错误消息中: Message=The following setups on mock .... were not matched: IReadAccess p => p.GetAll()
谢谢康奈尔,这是预期的工作,但我有类似的方法
public interface IReadAccess<TEntity>
{
Task<IEnumerable<TEntity>> GetAll();
Task<IEnumerable<TEntity>> Find(FormattableString whereClause, object whereClauseObject);
}
并尝试设置
var m = new Mock<IReadAccess<Foo>>(MockBehavior.Strict);
m.Setup(x => x.Find($"ID = @ID", new { ID = 5 })).ReturnsAsync(new List<Foo>());
var result = await m.Object.Find($"ID= @ID", new { ID = 5 });
m.VerifyAll();
在对现有代码进行一些更改后,现在设置工作正常,但在从测试调用时实际服务出现错误,更新代码
var test = new Test {ID = 5};
object whereClause = new { ID = test.ID };
FormattableString formattableString = $"ID = @ID";
m.Setup(x => x.Find(formattableString, whereClause)).ReturnsAsync(new List<Foo>());
var ruleServiceOutput = await this.testValidationRuleService.ExecuteAsync(test);
实际代码
public async Task<IRuleServiceOutput<bool>> ExecuteAsync(Test test)
{
var errors = new List<string>();
object whereClause = new { ID = test.ID };
FormattableString formattableString = $"ID = @ID";
var output = (await m.Find(formattableString, whereClause)).ToArray();
return new RuleServiceOutput<bool>(output.Errors.IsEmpty(), output.Errors);
}
'IReadAccess`1.Find(ID = @ID, { ID = 5 }) 调用失败,模拟行为严格。 模拟上的所有调用都必须具有相应的设置。'
设置 MockBehavior.Default 后一切正常:)