4

I have a class A that expose a HttpRequestHeaders as a property. The class under test is B.

  • B is using A.
  • A is also a fake class that is used only for unit test.
  • A inherit an interface that impose the definition of the HttpRequestHeaders property.

So I need to substitute the HttpRequestHeaders so that I can test B Unfortunately HttpRequestHeaders is a sealed class thus it can not be substitute by NSubstitute:

Could not load type 'Castle.Proxies.HttpRequestHeadersProxy_2' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=a621a9e7e5c32e69' because the parent type is sealed.

What would be the general solution to overcome this situation?

Amarnath Balasubramanian
  • 9,300
  • 8
  • 34
  • 62
mathk
  • 7,973
  • 6
  • 45
  • 74
  • 1
    why dont you break the dependency between B and A by interfacing A ? Extract an interface from A, and use it in B. – Alex Peta Feb 21 '14 at 09:40
  • @AlexPeta it is already the case. The interface require a `HttpRequestHeaders` property. It does not change the probleme – mathk Feb 21 '14 at 09:42
  • ok, then go one level up. make your on fake HttpRequestHeadersFake : HttpHeaders and use that in an implementation of FakeA – Alex Peta Feb 21 '14 at 09:45
  • @AlexPeta Why not but HttpRequestHeaders is not under my responsability it is a `System.Net.Http.Headers` class so I am not so keen on doing that. If I could I wouldn't mark this class as sealed afterall. – mathk Feb 21 '14 at 09:50
  • here is the source code for HttpRequestHeaders just so you dont have to write the whole thing : http://dotnetinside.com/en/framework/Microsoft+ASP.NET/System.Net.Http/HttpRequestHeaders. this will help you to create the fake class. i understand about the issue that is sealead. it sucks for unit testing but you can always bypass it :) – Alex Peta Feb 21 '14 at 09:53
  • Yes @AlexPeta thanks for your solution I will keep that if nobody come up with a better one. I really don't want to write the interface of `HttpRequestHeaders` – mathk Feb 21 '14 at 09:56
  • Why can't your fake `A` use a real `HttpRequestHeaders` object - just create an `HttpRequestMessage` object and grab its `Headers` property? – Damien_The_Unbeliever Feb 21 '14 at 09:57
  • @Damien_The_Unbeliever, I can not create a real `HttpRequestHeaders` because it is mark a internal $#%@@&5. And grabbing it from an other object could be the solution but it looks a bit heavy-handed. Anyway it seems the more appropriate solution. Thanks. Please wirte it as a proper answer and I will accept it – mathk Feb 21 '14 at 10:04

2 Answers2

5

Instead of trying to find a way to fake a sealed object, I'd instead look to see if I can get a real instance of one, assuming it doesn't have too many dependencies.

On the plus side, HttpRequestHeaders doesn't have too many dependencies. On the down side, it only has an internal constructor. Happily, though, HttpRequestMessage can be freely constructed and exposes a Headers property which will perform the required construction for you.

Alternatively, you might consider using reflection to create the object despite it only having the internal constructor - it's pick your poison time - create an unneeded, disposable object to cleanly create the headers, or start using reflection.

Damien_The_Unbeliever
  • 234,701
  • 27
  • 340
  • 448
1

Depending on the version of Visual Studio you're using, try Fakes (http://msdn.microsoft.com/en-us/library/hh549175.aspx)

This is especially useful if you don't have control over the dependencies.

iggymoran
  • 4,059
  • 2
  • 21
  • 26
  • Have you test that Fake won't behave the same as NSubstitute? – mathk Feb 21 '14 at 09:54
  • I have no experience with NSubstitute, but Fakes allows you to "fake" any class, even if it's sealed. It doesn't even need to be interface-based. It's great for introducing unit testing to legacy code where you have the type of restrictions you're describing. – iggymoran Feb 21 '14 at 10:00
  • 2
    Could be the solution but since I am using NSubstitute I don't want my project to load it with yet another framework. Thanks – mathk Feb 21 '14 at 10:09
  • NSubstitute does not use the profiler API, where as some other faking frameworks DO - which makes them much more powerful, especially if you don't control the code you are trying to fake. or you would have to test your functionality indirectly via Nsubstitute, which is another option. – BenKoshy Jan 09 '23 at 00:19