NSubstitute - TestFixture 1 导致 TestFixture 2 中的 AmbiguousArgumentsException [英] NSubstitute - TestFixture 1 causes AmbiguousArgumentsException in TestFixture 2

查看:65
本文介绍了NSubstitute - TestFixture 1 导致 TestFixture 2 中的 AmbiguousArgumentsException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 NUnit 和 NSubstitute 编写 C# 单元测试.我正在测试一个类,该类将尝试从实现以下接口的配置提供程序中检索对象:

I am writing C# unit tests using NUnit and NSubstitute. I am testing a class which will attempt to retrieve objects from a config provider implementing the following interface:

public interface IConfigProvider<T> {
    T GetConfig(int id);
    T GetConfig(string id);
}

被测试的类只使用 GetConfig 的 int 版本,所以在 SetUpFixture 中,我执行以下操作来设置一个始终返回相同虚拟对象的模拟配置提供程序:

The class being tested only uses the int version of GetConfig so in the SetUpFixture I do the following to set up a mocked config provider that will always return the same dummy object:

IConfigProvider<ConfigType> configProvider = Substitute.For<IConfigProvider<ConfigType>>();
configProvider.GetConfig(Arg.Any<int>()).Returns<ConfigType>(new ConfigType(/* args */);

如果 TestFixture 是唯一运行的,那么它运行绝对正常.但是,在同一个程序集中的不同 TestFixture 中,我检查收到的呼叫如下:

This runs absolutely fine if that TestFixture is the only one being run. However, in a different TestFixture in the same assembly, I check for received calls like this:

connection.Received(1).SetCallbacks(Arg.Any<Action<Message>>(), Arg.Any<Action<long>>(), Arg.Any<Action<long, Exception>>());

如果这些 Received 测试在配置提供程序测试之前运行,则配置测试在 SetUpFixture 中失败并出现 AmbiguousArgumentsException:

If these Received tests run before the config provider tests, then the config tests fail in the SetUpFixture with an AmbiguousArgumentsException:

Here.Be.Namespace.ProfileManagerTests+Setup (TestFixtureSetUp):
SetUp : NSubstitute.Exceptions.AmbiguousArgumentsException : Cannot determine argument specifications to use.
Please use specifications for all arguments of the same type.
at NSubstitute.Core.Arguments.NonParamsArgumentSpecificationFactory.Create(Object argument, IParameterInfo parameterInfo, ISuppliedArgumentSpecifications suppliedArgumentSpecifications)
at System.Linq.Enumerable.<SelectIterator>d__7`2.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at NSubstitute.Core.Arguments.MixedArgumentSpecificationsFactory.Create(IList`1 argumentSpecs, Object[] arguments, IParameterInfo[] parameterInfos)
at NSubstitute.Core.Arguments.ArgumentSpecificationsFactory.Create(IList`1 argumentSpecs, Object[] arguments, IParameterInfo[] parameterInfos, MatchArgs matchArgs)
at NSubstitute.Core.CallSpecificationFactory.CreateFrom(ICall call, MatchArgs matchArgs)
at NSubstitute.Routing.Handlers.RecordCallSpecificationHandler.Handle(ICall call)
at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
at NSubstitute.Routing.Route.Handle(ICall call)
at NSubstitute.Proxies.CastleDynamicProxy.CastleForwardingInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.IConfigProvider`1Proxy.GetConfig(Int32 id)
at Here.Be.Namespace.ProfileManagerTests.Setup.DoSetup()

真正让我困惑的是,即使在测试运行之间我也可以观察到这种效果 - 如果我使用 NUnit GUI 单独运行 Received 测试,然后单独运行配置测试,配置测试将失败.如果我立即再次运行配置测试,它们将通过.

What's really confusing me is that I can observe this effect even between test runs - if I use the NUnit GUI to run the Received tests alone, and then run the config tests alone, the config tests will fail. If I then immediately run the config tests again, they will pass.

我尝试过的事情:

  • 添加 configProvider.GetConfig(Arg.Any<string>()).Returns... 以及,以防重载是问题.
  • 我已经阅读了 关于参数匹配的 NSubstitute 文档,但我在那里找不到解决方案.如果必须为该方法的 int 和 string 版本提供参数匹配器,我不知道该怎么做.
  • Adding configProvider.GetConfig(Arg.Any<string>()).Returns... as well, in case the overloading was the problem.
  • I've read the NSubstitute docs on argument matching, but I can't find a solution there. If it is a case of having to supply argument matchers for both the int and string versions of the method, I can't work out how to do that.

碰巧的是,我使用的测试只会调用值为 0 或 1 的 GetConfig 方法,因此我可以为这些测试提供 Returns 规范两个值,根本不使用匹配,但我想了解如何更一般地解决这个问题.

As it happens, the tests I'm using will only ever call the GetConfig method with values of 0 or 1, so I can just provide Returns specifications for those two values and not use matching at all, but I want to understand how to fix this more generally.

推荐答案

歧义参数是当 NSubstitute 将参数与其当前正在使用的调用进行比较时,与其拥有的参数匹配器"堆栈(每次 Arg.Blah 被调用,一个参数匹配器被添加到该堆栈中),并且无法解析哪个参数去哪里.

Ambiguous arguments is when NSubstitute compares the arguments to the call it is currently working with, to the stack of "argument matchers" it has (each time Arg.Blah is called, an the argument matcher is added to that stack), and it is unable to resolve which argument goes where.

通常这是由于调用像 blah(null, null) 和单个参数匹配器排队引起的,但也可能是由于堆栈不同步造成的到在调用配置之外使用的 arg 匹配器,或作为非虚拟方法的参数.

Normally this is caused by having a call like blah(null, null), with a single argument matcher queued up, but it can also be caused by the stack getting out-of-sync due to an arg matcher being used outside of call configuration, or as an argument to a non-virtual method.

1.8.0 版(在您提出问题后发布)对后一种情况的检测略有改进,因此可能值得一试.

Version 1.8.0 (released after your question) includes slightly improved detection of the latter case, so that may be worth trying.

除此之外,我遇到过几次这个问题,并使用了以下(痛苦的)方法.

Other than that, I've had this problem a few times and have used the following (painful) approach.

  • 单独运行测试并确保它通过
  • 找出立即运行的测试(通常可以猜测,但测试日志在这里可以提供帮助),然后只运行这两个测试.确认失败.
  • 查找任何对 Arg.xyz 的调用,这些调用可能会在任一测试中排队参数匹配器.确保它用作呼叫配置的一部分.有时可以通过注释掉行或用其他值替换 arg 匹配器来确定哪个调用有问题.
  • 确保没有调用使 NSubstitute 感到困惑的非虚拟方法.
  • run the test in isolation and ensure it passes
  • work out what test runs immediately proceeding (can usually guess, but test logs can help here), and run just those two tests. Confirm it fails.
  • Look for any calls to Arg.xyz that could queue up an argument matcher in either test. Make sure it is used as part of a call configuration. Sometimes working out which call is problematic can be done by commenting out lines or replacing arg matchers with other values.
  • Make sure there are no calls to non-virtual methods that are confusing NSubstitute.

有时问题可能是由于之前的固定装置造成的,因此您可能需要锻炼之前的固定装置并在那里进行探索.:(

Sometimes the problem may be due to a previous fixture, so you may need to workout the previous fixture and explore there as well. :(

这篇关于NSubstitute - TestFixture 1 导致 TestFixture 2 中的 AmbiguousArgumentsException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆