- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我目前正在为 CommandHandler 编写单元测试。我使用 Moq 4.12.0 和 xUnit 2.4.1 进行测试。我想验证是否使用某个 NSpecification 调用了一个方法.
我是单元测试领域的新手。
这是 CommandHandler:
public class DeleteAlarmCodesCommandHandler : IRequestHandler<DeleteAlarmCodesCommand, CommandResult<IEnumerable<AlarmCode>>>
{
private readonly Domain.Model.IAlarmCodeRepository _alarmCodeRepository;
public DeleteAlarmCodesCommandHandler(
Domain.Model.IAlarmCodeRepository alarmCodeRepository)
{
_alarmCodeRepository = alarmCodeRepository;
}
public async Task<CommandResult<IEnumerable<AlarmCode>>> Handle(DeleteAlarmCodesCommand request, CancellationToken cancellationToken)
{
ASpec<Domain.Model.AlarmCode> spec = Spec<Domain.Model.AlarmCode>.Any;
if (request.AlarmId != null)
{
spec &= Domain.Model.AlarmCodeSpecifications.ForAlarmId(request.AlarmId);
}
if (request.LanguageISO != null)
{
spec &= Domain.Model.AlarmCodeSpecifications.ForLanguageISO(request.LanguageISO);
}
try
{
var alarmCodes = await _alarmCodeRepository.DeleteAsync(spec);
await _alarmCodeRepository.SaveAsync();
return new CommandResult<IEnumerable<AlarmCode>>(alarmCodes.Select(x => x.ToViewModel()));
}
catch (Domain.ApiDomainException ex)
{
return new CommandResult<IEnumerable<AlarmCode>>(ApiErrors.FromException(ex));
}
}
}
这是我的单元测试,用于检查是否根据规范调用了 DeleteAsync()。
[Fact]
public async Task Should_DeleteWithAlarmIdOne_WhenCalledWitParameterAlarmIdOne()
{
// Arrange
var repo = new Mock<IAlarmCodeRepository>();
var command = new DeleteAlarmCodesCommand() { AlarmId = 1 };
var commandHandler = new DeleteAlarmCodesCommandHandler(repo.Object);
// Act
var result = await commandHandler.Handle(command, It.IsAny<CancellationToken>());
var spec = Spec<AlarmCode>.Any & AlarmCodeSpecifications.ForAlarmId(command.AlarmId);
// Assert
repo.Verify(x => x.DeleteAsync(spec), Times.Once);
repo.Verify(x => x.SaveAsync(), Times.Once);
}
问题是对两个对象的引用是不同的,因为它们是在需要时创建的。所以 Moq 将它们视为完全不同的对象。因为当我运行测试时,我在结果 Pane 中得到以下结果。
Duration: 182 ms
Message:
Moq.MockException :
Expected invocation on the mock once, but was 0 times: x => x.DeleteAsync(x => (True AndAlso (Convert(Convert(x.AlarmId, Int32), Nullable`1) == Convert(value(Services.Domain.Model.AlarmCodeSpecifications+<>c__DisplayClass0_0).alarmId, Nullable`1))))
Performed invocations:
Mock<IAlarmCodeRepository:1> (x):
IAlarmCodeRepository.DeleteAsync(x => (True AndAlso (Convert(Convert(x.AlarmId, Int32), Nullable`1) == Convert(value(Services.Domain.Model.AlarmCodeSpecifications+<>c__DisplayClass0_0).alarmId, Nullable`1))))
IRepository`1.SaveAsync()
Stack Trace:
Mock.Verify(Mock mock, LambdaExpression expression, Times times, String failMessage)
Mock`1.Verify[TResult](Expression`1 expression, Func`1 times)
DeleteAlarmCodesCommandHandler_Handle.Should_DeleteWithAlarmIdOne_WhenCalledWitParameterAlarmIdOne() line 46
--- End of stack trace from previous location where exception was thrown ---
是否有一种方法可以通过 Moq 来验证具有复杂对象(例如 Spec)的调用。
或者我怎样才能更好地测试它?
更新
这是 IAlarmCodeRepository 的定义。
public interface IAlarmCodeRepository : IRepository<AlarmCode>
{
IUnitOfWork UnitOfWork { get; }
Task AddAsync(AlarmCode entity);
Task<AlarmCode> GetOneAsync(int id);
Task<AlarmCode> GetOneAsync(ASpec<AlarmCode> spec);
Task<IEnumerable<AlarmCode>> FindAsync(ASpec<AlarmCode> spec);
Task<bool> Exists(ASpec<AlarmCode> spec);
Task<IEnumerable<AlarmCode>> DeleteAsync(ASpec<AlarmCode> spec);
Task<AlarmCode> DeleteOne(int id);
Task<IEnumerable<short>> GetDistinctAlarmIds();
}
public interface IRepository<T>
where T : IAggregateRoot
{
Task SaveAsync();
}
public async Task SaveAsync()
{
await UnitOfWork.CommitAsync();
}
这是 AlarmSpecifications。
public static class AlarmCodeSpecifications
{
public static ASpec<AlarmCode> ForAlarmId(short? alarmId)
{
return new Spec<AlarmCode>(o => o.AlarmId == alarmId);
}
}
Spec 和 ASpec 来自 https://github.com/jnicolau/NSpecifications 上的 NSpecifications 库: https://github.com/jnicolau/NSpecifications/blob/master/Nspecifications/ASpec.cs
最佳答案
由于缺少信息,必须做出一些假设,但以下内容应该提供足够的平台来理解如何练习被测对象
[Fact]
public async Task Should_DeleteWithAlarmIdOne_WhenCalledWitParameterAlarmIdOne() {
// Arrange
short? expectedAlarmId = 1;
var alarmCode = new AlarmCode { AlarmId = expectedAlarmId };
var alarmCodes = new List<AlarmCode>(alarmCode);
var repo = new Mock<IAlarmCodeRepository>();
//fake the desired functionality
repo.Setup(_ => _.DeleteAsync(It.IsAny<ASpec<AlarmCode>>()))
.ReturnsAsync((ASpec<AlarmCode> arg) => alarmCodes.Where(arg));
//allow async flow
repo.Setup(_ => _.SaveAsync()).ReturnsAsync(Task.CompletedTask); //assuming it it void (Task)
var command = new DeleteAlarmCodesCommand() { AlarmId = expectedAlarmId };
var commandHandler = new DeleteAlarmCodesCommandHandler(repo.Object);
// Act
var result = await commandHandler.Handle(command, default(CancellationToken));
// Assert
var expected = Spec<AlarmCode>.Any & AlarmCodeSpecifications.ForAlarmId(command.AlarmId);
repo.Verify(x => x.DeleteAsync(It.Is<ASpec<AlarmCode>>(actual => actual == expected)), Times.Once);
repo.Verify(x => x.SaveAsync(), Times.Once);
}
关于c# - 如何在 C# 单元测试中验证具有特定 NSpecification 参数的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58393570/
在 JSF2 应用程序中遇到验证属性的问题时,有两种主要方法。 使用 Annotation 在 ManagedBean 上定义验证 @ManagedBean public class MyBean {
我想实现一个不常见的功能,我认为 jquery 验证插件将是最好的方法(如果您在没有插件的情况下建议和回答,我们也会欢迎)。我想在用户在输入字段中输入正确的单词后立即隐藏表单。我试过这个: $("
我有几个下拉菜单(类名为month_dropdown),并且下拉菜单的数量不是恒定的。我怎样才能为它们实现 NotEqual 验证。我正在使用 jQuery 验证插件。 这就是我写的 - jQuery
我设法制作了这个网址验证代码并且它起作用了。但我面临着一个问题。我认为 stackoverflow 是获得解决方案的最佳场所。 function url_followers(){ var url=do
我目前正在使用后端服务,该服务允许用户在客户端应用程序上使用 Google Games 库登录。 用户可以通过他们的 gplay ID 向我们发送信息,以便登录或恢复旧帐户。用户向我们发送以下内容,包
我正在尝试验证输入以查看它是否是有效的 IP 地址(可能是部分地址)。 可接受的输入:172、172.112、172.112.113、172.112.113.114 Not Acceptable 输入
我从 Mongoose 验证中得到这条消息: 'Validator failed for path phone with value ``' 这不应该发生,因为不需要电话。 这是我的模型架构: var
我一直在尝试使用Python-LDAP (版本 2.4.19)在 MacOS X 10.9.5 和 Python 2.7.9 下 我想在调用 .start_tls_s() 后验证与给定 LDAP 服务
我正在处理一个仅与 IE6 兼容的旧 javascript 项目(抱歉...),我想仅在 VS 2017 中禁用此项目的 ESLint/CSLint/Javascript 验证/CSS 验证。 我知道
我正在寻找一种方法来验证 Spring 命令 bean 中的 java.lang.Double 字段的最大值和最小值(一个值必须位于给定的值范围之间),例如, public final class W
我正在尝试在 springfuse(JavaEE 6 + Spring Framework (针对 Jetty、Tomcat、JBoss 等)) 和 maven 的帮助下构建我的 webapps 工作
我试图在我们的项目中使用 scalaz 验证,但遇到了以下情况: def rate(username: String, params: Map[String, String]): Validation
我有一个像这样的 Yaml 文件 name: hhh_aaa_bbb arguments: - !argument name: inputsss des
我有一个表单,人们可以单击并向表单添加字段,并且我需要让它在单击时验证这些字段中的值。 假设我单击它两次并获取 2 个独立的字段集,我需要旋转 % 以确保它在保存时等于 100。 我已放入此函数以使其
在我的页面中有一个选项可以创建新的日期字段输入框。用户可以根据需要创建尽可能多的“截止日期”和“起始日期”框。就像, 日期_to1 || date_from1 日期到2 ||日期_from2 date
我有一个像这样的 Yaml 文件 name: hhh_aaa_bbb arguments: - !argument name: inputsss des
有没有办法在动态字段上使用 jquery 验证表单。 我想将其设置为必填字段 我正在使用 Jsp 动态创建表单字段。 喜欢 等等...... 我想使用必需的表单字段验证此表单字段。 最佳答
嗨,任何人都可以通过提供 JavaScript 代码来帮助我验证用户名文本框不应包含数字,它只能包含一个字符。 最佳答案 使用正则表达式: (\d)+ 如果找到匹配项,则字符串中就有一个数字。 关于J
我有两个输入字段holidayDate和Description(id=tags) $(document).ready(function() {
我遇到了这个问题,这些验证从电子邮件验证部分开始就停止工作。 我只是不明白为什么即使经过几天的观察,只是想知道是否有人可以在这里指出我的错误? Javascript部分: function valid
我是一名优秀的程序员,十分优秀!