Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ArgumentNullException while mocking a large interface in a unit test project #120

Closed
helix87 opened this issue Oct 25, 2013 · 6 comments
Closed

Comments

@helix87
Copy link

helix87 commented Oct 25, 2013

Hello,

I have to mock a large interface (~630 methods).

Im using the TestInitialize method to create new mocks for every unit test where _mJob = Substitute.For(Of IJobInterface)() throws an ArgumentNullException.

The same line in a test form (non unit test project) seems to work.

Thank you

@dtchepak
Copy link
Member

I can't reproduce this. Can you post a stack trace? Is anything else unusual about IJobInterface?

using NUnit.Framework;

namespace NSubstitute.Acceptance.Specs.FieldReports
{
    public class Issue120_LargeInterface
    {
        [Test]
        public void SubForLargeInterface()
        {
            var sub = Substitute.For<ILargeInterface>();
            sub.Method42();
        }

        public interface ILargeInterface
        {
            void Method0();
            void Method1();
            void Method2();
            void Method3();
            void Method4();
            void Method5();
            void Method6();
            void Method7();
            void Method8();
            void Method9();
            void Method10();
            void Method11();
            void Method12();
            void Method13();
            void Method14();
            void Method15();
            void Method16();
            void Method17();
            void Method18();
            void Method19();
            void Method20();
            void Method21();
            void Method22();
            void Method23();
            void Method24();
            void Method25();
            void Method26();
            void Method27();
            void Method28();
            void Method29();
            void Method30();
            void Method31();
            void Method32();
            void Method33();
            void Method34();
            void Method35();
            void Method36();
            void Method37();
            void Method38();
            void Method39();
            void Method40();
            void Method41();
            void Method42();
            void Method43();
            void Method44();
            void Method45();
            void Method46();
            void Method47();
            void Method48();
            void Method49();
            void Method50();
            void Method51();
            void Method52();
            void Method53();
            void Method54();
            void Method55();
            void Method56();
            void Method57();
            void Method58();
            void Method59();
            void Method60();
            void Method61();
            void Method62();
            void Method63();
            void Method64();
            void Method65();
            void Method66();
            void Method67();
            void Method68();
            void Method69();
            void Method70();
            void Method71();
            void Method72();
            void Method73();
            void Method74();
            void Method75();
            void Method76();
            void Method77();
            void Method78();
            void Method79();
            void Method80();
            void Method81();
            void Method82();
            void Method83();
            void Method84();
            void Method85();
            void Method86();
            void Method87();
            void Method88();
            void Method89();
            void Method90();
            void Method91();
            void Method92();
            void Method93();
            void Method94();
            void Method95();
            void Method96();
            void Method97();
            void Method98();
            void Method99();
            void Method100();
            void Method101();
            void Method102();
            void Method103();
            void Method104();
            void Method105();
            void Method106();
            void Method107();
            void Method108();
            void Method109();
            void Method110();
            void Method111();
            void Method112();
            void Method113();
            void Method114();
            void Method115();
            void Method116();
            void Method117();
            void Method118();
            void Method119();
            void Method120();
            void Method121();
            void Method122();
            void Method123();
            void Method124();
            void Method125();
            void Method126();
            void Method127();
            void Method128();
            void Method129();
            void Method130();
            void Method131();
            void Method132();
            void Method133();
            void Method134();
            void Method135();
            void Method136();
            void Method137();
            void Method138();
            void Method139();
            void Method140();
            void Method141();
            void Method142();
            void Method143();
            void Method144();
            void Method145();
            void Method146();
            void Method147();
            void Method148();
            void Method149();
            void Method150();
            void Method151();
            void Method152();
            void Method153();
            void Method154();
            void Method155();
            void Method156();
            void Method157();
            void Method158();
            void Method159();
            void Method160();
            void Method161();
            void Method162();
            void Method163();
            void Method164();
            void Method165();
            void Method166();
            void Method167();
            void Method168();
            void Method169();
            void Method170();
            void Method171();
            void Method172();
            void Method173();
            void Method174();
            void Method175();
            void Method176();
            void Method177();
            void Method178();
            void Method179();
            void Method180();
            void Method181();
            void Method182();
            void Method183();
            void Method184();
            void Method185();
            void Method186();
            void Method187();
            void Method188();
            void Method189();
            void Method190();
            void Method191();
            void Method192();
            void Method193();
            void Method194();
            void Method195();
            void Method196();
            void Method197();
            void Method198();
            void Method199();
            void Method200();
            void Method201();
            void Method202();
            void Method203();
            void Method204();
            void Method205();
            void Method206();
            void Method207();
            void Method208();
            void Method209();
            void Method210();
            void Method211();
            void Method212();
            void Method213();
            void Method214();
            void Method215();
            void Method216();
            void Method217();
            void Method218();
            void Method219();
            void Method220();
            void Method221();
            void Method222();
            void Method223();
            void Method224();
            void Method225();
            void Method226();
            void Method227();
            void Method228();
            void Method229();
            void Method230();
            void Method231();
            void Method232();
            void Method233();
            void Method234();
            void Method235();
            void Method236();
            void Method237();
            void Method238();
            void Method239();
            void Method240();
            void Method241();
            void Method242();
            void Method243();
            void Method244();
            void Method245();
            void Method246();
            void Method247();
            void Method248();
            void Method249();
            void Method250();
            void Method251();
            void Method252();
            void Method253();
            void Method254();
            void Method255();
            void Method256();
            void Method257();
            void Method258();
            void Method259();
            void Method260();
            void Method261();
            void Method262();
            void Method263();
            void Method264();
            void Method265();
            void Method266();
            void Method267();
            void Method268();
            void Method269();
            void Method270();
            void Method271();
            void Method272();
            void Method273();
            void Method274();
            void Method275();
            void Method276();
            void Method277();
            void Method278();
            void Method279();
            void Method280();
            void Method281();
            void Method282();
            void Method283();
            void Method284();
            void Method285();
            void Method286();
            void Method287();
            void Method288();
            void Method289();
            void Method290();
            void Method291();
            void Method292();
            void Method293();
            void Method294();
            void Method295();
            void Method296();
            void Method297();
            void Method298();
            void Method299();
            void Method300();
            void Method301();
            void Method302();
            void Method303();
            void Method304();
            void Method305();
            void Method306();
            void Method307();
            void Method308();
            void Method309();
            void Method310();
            void Method311();
            void Method312();
            void Method313();
            void Method314();
            void Method315();
            void Method316();
            void Method317();
            void Method318();
            void Method319();
            void Method320();
            void Method321();
            void Method322();
            void Method323();
            void Method324();
            void Method325();
            void Method326();
            void Method327();
            void Method328();
            void Method329();
            void Method330();
            void Method331();
            void Method332();
            void Method333();
            void Method334();
            void Method335();
            void Method336();
            void Method337();
            void Method338();
            void Method339();
            void Method340();
            void Method341();
            void Method342();
            void Method343();
            void Method344();
            void Method345();
            void Method346();
            void Method347();
            void Method348();
            void Method349();
            void Method350();
            void Method351();
            void Method352();
            void Method353();
            void Method354();
            void Method355();
            void Method356();
            void Method357();
            void Method358();
            void Method359();
            void Method360();
            void Method361();
            void Method362();
            void Method363();
            void Method364();
            void Method365();
            void Method366();
            void Method367();
            void Method368();
            void Method369();
            void Method370();
            void Method371();
            void Method372();
            void Method373();
            void Method374();
            void Method375();
            void Method376();
            void Method377();
            void Method378();
            void Method379();
            void Method380();
            void Method381();
            void Method382();
            void Method383();
            void Method384();
            void Method385();
            void Method386();
            void Method387();
            void Method388();
            void Method389();
            void Method390();
            void Method391();
            void Method392();
            void Method393();
            void Method394();
            void Method395();
            void Method396();
            void Method397();
            void Method398();
            void Method399();
            void Method400();
            void Method401();
            void Method402();
            void Method403();
            void Method404();
            void Method405();
            void Method406();
            void Method407();
            void Method408();
            void Method409();
            void Method410();
            void Method411();
            void Method412();
            void Method413();
            void Method414();
            void Method415();
            void Method416();
            void Method417();
            void Method418();
            void Method419();
            void Method420();
            void Method421();
            void Method422();
            void Method423();
            void Method424();
            void Method425();
            void Method426();
            void Method427();
            void Method428();
            void Method429();
            void Method430();
            void Method431();
            void Method432();
            void Method433();
            void Method434();
            void Method435();
            void Method436();
            void Method437();
            void Method438();
            void Method439();
            void Method440();
            void Method441();
            void Method442();
            void Method443();
            void Method444();
            void Method445();
            void Method446();
            void Method447();
            void Method448();
            void Method449();
            void Method450();
            void Method451();
            void Method452();
            void Method453();
            void Method454();
            void Method455();
            void Method456();
            void Method457();
            void Method458();
            void Method459();
            void Method460();
            void Method461();
            void Method462();
            void Method463();
            void Method464();
            void Method465();
            void Method466();
            void Method467();
            void Method468();
            void Method469();
            void Method470();
            void Method471();
            void Method472();
            void Method473();
            void Method474();
            void Method475();
            void Method476();
            void Method477();
            void Method478();
            void Method479();
            void Method480();
            void Method481();
            void Method482();
            void Method483();
            void Method484();
            void Method485();
            void Method486();
            void Method487();
            void Method488();
            void Method489();
            void Method490();
            void Method491();
            void Method492();
            void Method493();
            void Method494();
            void Method495();
            void Method496();
            void Method497();
            void Method498();
            void Method499();
            void Method500();
            void Method501();
            void Method502();
            void Method503();
            void Method504();
            void Method505();
            void Method506();
            void Method507();
            void Method508();
            void Method509();
            void Method510();
            void Method511();
            void Method512();
            void Method513();
            void Method514();
            void Method515();
            void Method516();
            void Method517();
            void Method518();
            void Method519();
            void Method520();
            void Method521();
            void Method522();
            void Method523();
            void Method524();
            void Method525();
            void Method526();
            void Method527();
            void Method528();
            void Method529();
            void Method530();
            void Method531();
            void Method532();
            void Method533();
            void Method534();
            void Method535();
            void Method536();
            void Method537();
            void Method538();
            void Method539();
            void Method540();
            void Method541();
            void Method542();
            void Method543();
            void Method544();
            void Method545();
            void Method546();
            void Method547();
            void Method548();
            void Method549();
            void Method550();
            void Method551();
            void Method552();
            void Method553();
            void Method554();
            void Method555();
            void Method556();
            void Method557();
            void Method558();
            void Method559();
            void Method560();
            void Method561();
            void Method562();
            void Method563();
            void Method564();
            void Method565();
            void Method566();
            void Method567();
            void Method568();
            void Method569();
            void Method570();
            void Method571();
            void Method572();
            void Method573();
            void Method574();
            void Method575();
            void Method576();
            void Method577();
            void Method578();
            void Method579();
            void Method580();
            void Method581();
            void Method582();
            void Method583();
            void Method584();
            void Method585();
            void Method586();
            void Method587();
            void Method588();
            void Method589();
            void Method590();
            void Method591();
            void Method592();
            void Method593();
            void Method594();
            void Method595();
            void Method596();
            void Method597();
            void Method598();
            void Method599();
            void Method600();
            void Method601();
            void Method602();
            void Method603();
            void Method604();
            void Method605();
            void Method606();
            void Method607();
            void Method608();
            void Method609();
            void Method610();
            void Method611();
            void Method612();
            void Method613();
            void Method614();
            void Method615();
            void Method616();
            void Method617();
            void Method618();
            void Method619();
            void Method620();
            void Method621();
            void Method622();
            void Method623();
            void Method624();
            void Method625();
            void Method626();
            void Method627();
            void Method628();
            void Method629();
            void Method630();
            void Method631();
            void Method632();
            void Method633();
            void Method634();
            void Method635();
            void Method636();
            void Method637();
            void Method638();
            void Method639();
            void Method640();
            void Method641();
            void Method642();
            void Method643();
            void Method644();
            void Method645();
            void Method646();
            void Method647();
            void Method648();
            void Method649();
            void Method650();
            void Method651();
            void Method652();
            void Method653();
            void Method654();
            void Method655();
            void Method656();
            void Method657();
            void Method658();
            void Method659();
            void Method660();
            void Method661();
            void Method662();
            void Method663();
            void Method664();
            void Method665();
            void Method666();
            void Method667();
            void Method668();
            void Method669();
            void Method670();
            void Method671();
            void Method672();
            void Method673();
            void Method674();
            void Method675();
            void Method676();
            void Method677();
            void Method678();
            void Method679();
            void Method680();
            void Method681();
            void Method682();
            void Method683();
            void Method684();
            void Method685();
            void Method686();
            void Method687();
            void Method688();
            void Method689();
            void Method690();
            void Method691();
            void Method692();
            void Method693();
            void Method694();
            void Method695();
            void Method696();
            void Method697();
            void Method698();
            void Method699();
            void Method700();
        }
    }
}

@helix87
Copy link
Author

helix87 commented Oct 28, 2013

Hello dtchepak,

it's weird but the ArgumentNullException does not occure every time. Here is the stack trace:

mscorlib.dll!System.Reflection.Emit.TypeBuilder.InternalSetMethodIL + 0x88 bytes        mscorlib.dll!System.Reflection.Emit.TypeBuilder.CreateTypeNoLock + 0xce8 bytes  
mscorlib.dll!System.Reflection.Emit.TypeBuilder.CreateType + 0xa9 bytes 
NSubstitute.dll!Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.CreateType + 0x14c bytes    
NSubstitute.dll!Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType + 0x108 bytes 
NSubstitute.dll!Castle.DynamicProxy.Generators.InterfaceProxyWithoutTargetGenerator.GenerateType + 0x5d6 bytes  
NSubstitute.dll!Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.<>c__DisplayClass1.<GenerateCode>b__0 + 0x167 bytes    
NSubstitute.dll!Castle.DynamicProxy.Generators.BaseProxyGenerator.ObtainProxyType + 0x58c bytes 
NSubstitute.dll!Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.GenerateCode + 0x2e2 bytes 
NSubstitute.dll!Castle.DynamicProxy.DefaultProxyBuilder.CreateInterfaceProxyTypeWithoutTarget + 0x21a bytes 
NSubstitute.dll!Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyTypeWithoutTarget + 0x1ac bytes  
NSubstitute.dll!Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget + 0x29a bytes  
NSubstitute.dll!NSubstitute.Proxies.CastleDynamicProxy.CastleDynamicProxyFactory.CreateProxyUsingCastleProxyGenerator + 0x246 bytes 
NSubstitute.dll!NSubstitute.Proxies.CastleDynamicProxy.CastleDynamicProxyFactory.GenerateProxy + 0x1ff bytes    
NSubstitute.dll!NSubstitute.Proxies.ProxyFactory.GenerateProxy + 0x1d5 bytes    
NSubstitute.dll!NSubstitute.Core.SubstituteFactory.Create + 0x1dd bytes 
NSubstitute.dll!NSubstitute.Substitute.For + 0x12d bytes    
NSubstitute.dll!NSubstitute.Substitute.For + 0x1c7 bytes    
NSubstituteTestProject.dll!NSubstituteTestProject.NSubTestClass.GetFlagnoteIdListTestWithNSub() Line 77 + 0x1d bytes    Basic
[Native to Managed Transition]  
[Managed to Native Transition]  
Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter.dll!Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestExecuter.RunTestMethod + 0x10e bytes  
Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter.dll!Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestExecuter.ExecuteTest + 0xd7 bytes 
Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter.dll!Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestExecuter.Execute + 0xc6 bytes 
Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter.dll!Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestRunner.ExecuteSingleTest + 0x97 bytes 
Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter.dll!Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestRunner.ExecuteSingleTest + 0x95 bytes 
Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter.dll!Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestRunner.Run + 0x3a3 bytes  
[Appdomain Transition]  
Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter.dll!Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestAdapter.Run + 0x73a bytes 
Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter.dll!Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestAdapter.Run + 0x3c bytes  
Microsoft.VisualStudio.QualityTools.AgentObject.dll!Microsoft.VisualStudio.TestTools.Agent.AgentExecution.CallAdapterRunMethod + 0x209 bytes    
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context + 0xf0 bytes 
mscorlib.dll!System.Threading.ExecutionContext.Run + 0x111 bytes    
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart + 0x72 bytes 

There is also a performance problem with that line. It takes several minutes and several GBytes of memory. Sometimes it leads to a OutOfMemory exception:

memoryconsumption

IJobInterface is an Interface of a C++ COM class if it's important for you. Here is the Interop.dll. Add it as a reference and import the e3 namespace.

[ DT: link removed ]

There are a lot more interfaces inside just ignore them.

Greetings

@helix87
Copy link
Author

helix87 commented Nov 4, 2013

Hello,

any ideas or do you need more information?

Cheers

@dtchepak
Copy link
Member

dtchepak commented Nov 4, 2013

I haven't had a chance to chase it up yet sorry. Uneducated guess is that it is something specific to the types in the DLL as the interface size itself doesn't seem to be a problem. Might be some static initialisation on type reference?

One thing that is worth a try is to see if the problem is with NSub or with Castle Dynamic Proxy, which we use to create the proxy type. There's an example of how to do this in the NSub codebase where we call Dynamic Proxy (using a do-nothing IInterceptor implementation should be fine). If it fails without NSub then we'll need to bug the good people at the Castle Project. Can you try that against IJobInterface?

As a workaround, maybe create your own type with the interface you need, then have a concrete implementation that delegates to an IJobInterface? (or use an Adapter between the two interfaces?) You can then test against a smaller interface that represents what you need, and use the C++ COM implementation under the hood.

@helix87
Copy link
Author

helix87 commented Nov 4, 2013

There are no static initialisation as far as I know.

The IJobInterface contains a total of 6000 methods because it inherits previous versions of the interface ( last 10 versions each with ~ 600 methods). Actually it would be enough when the mock implements only a specific or only the newest version of the interface. This should reduce the amount of methods to be implemented to ~600 which does not seem to result in a performance issue as you already tried.
Maybe it will help in further investigation.

I never did anything with proxies but i'll give it a try when I have some time to spare.

Meanwhile I tried some other mocking frameworks - the job object is always the problem except for RhinoMocks.
With the DynamicMockWithRemoting class IJobInterface is mocked in no time. Although I have to ask myself what this mock actually doesn't have compared to the others...

@dtchepak
Copy link
Member

dtchepak commented Oct 7, 2017

This is for a very old version of the library. Closing as part of a general cleanup of issues. Please re-open if any action is still required.

@dtchepak dtchepak closed this as completed Oct 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants