How do you mock a Sealed class?

44,442

Solution 1

My general rule of thumb is that objects that I need to mock should have a common interface too. I think this is right design-wise and makes tests a lot easier (and is usually what you get if you do TDD). More about this can be read in the Google Testing Blog latest post (See point 9).

Also, I've been working mainly in Java in the past 4 years and I can say that I can count on one hand the number of times I've created a final (sealed) class. Another rule here is I should always have a good reason to seal a class, as opposed to sealing it by default.

Solution 2

For .NET, you could use something like TypeMock, which uses the profiling API and allows you to hook into calls to nearly anything.

Solution 3

I believe that Moles, from Microsoft Research, allows you to do that. From the Moles page:

Moles may be used to detour any .NET method, including non-virtual/static methods in sealed types.

UPDATE: there is a new framework called "Fakes" in the upcoming VS 11 release that is designed to replace Moles:

The Fakes Framework in Visual Studio 11 is the next generation of Moles & Stubs, and will eventually replace it. Fakes is different from Moles, however, so moving from Moles to Fakes will require some modifications to your code. A guide for this migration will be available at a later date.

Requirements: Visual Studio 11 Ultimate, .NET 4.5

Solution 4

The problem with TypeMock is that it excuses bad design. Now, I know that it is often someone else's bad design that it's hiding, but permitting it into your development process can lead very easily to permitting your own bad designs.

I think if you're going to use a mocking framework, you should use a traditional one (like Moq) and create an isolation layer around the unmockable thing, and mock the isolation layer instead.

Solution 5

I came across this problem recently and after reading / searching web, seems like there is no easy way around except to use another tool as mentioned above. Or crude of handling things as I did:

  • Create instance of sealed class without getting constructor called.
  • System.Runtime.Serialization.FormatterServices.GetUninitializedObject(instanceType);

  • Assign values to your properties / fields via reflection

  • YourObject.GetType().GetProperty("PropertyName").SetValue(dto, newValue, null);
  • YourObject.GetType().GetField("FieldName").SetValue(dto, newValue);
Share:
44,442
scoopr
Author by

scoopr

Disciple, Husband, Father, Brother, Son... Programmer

Updated on April 11, 2021

Comments

  • scoopr
    scoopr about 3 years

    Mocking sealed classes can be quite a pain. I currently favor an Adapter pattern to handle this, but something about just keeps feels weird.

    So, What is the best way you mock sealed classes?

    Java answers are more than welcome. In fact, I would anticipate that the Java community has been dealing with this longer and has a great deal to offer.

    But here are some of the .NET opinions:

  • Bryan Watts
    Bryan Watts about 15 years
    I would argue that you should have a good reason not to seal a class. Leaving a class open means you need to think about how it will be used by inheritors, which opens up a floodgate of decisions about all the code in the class (virtuality, protected properties or private member variables, etc.) It is hard to properly design a class for inheritance. You shouldn't be able to extend a class just for extension's sake; derivation should mean something specific to the problem being modeled. Otherwise, favor composition instead.
  • Pavel Minaev
    Pavel Minaev over 14 years
    Not slapping interfaces on everything in sight just because you need them because of deficiencies of your testing tools is not bad design. In fact, quite the opposite - it's sane design that is about design, not about conforming to your tools. I swear, sometimes I think that TDD as it's often dogmatically practiced should really be called "tools-driven design". Also see weblogs.asp.net/rosherove/archive/2008/01/17/…
  • Pavel Minaev
    Pavel Minaev over 14 years
    +1. Use the right tools. Don't let tools dictate you how you should do things. APIs are for people, not for tools - design them as such. Use DI and interfaces and full decoupling where it makes sense, not just because you need it for testing tools.
  • Beep beep
    Beep beep over 14 years
    Bryan - so how would you mock a sealed class then? I agree with you from a theoretical standpoint, but if you write something dependent on your sealed class then your tests depend on the sealed class as well.
  • Beep beep
    Beep beep over 14 years
    Pavel - the problem is that the "Right" way in .NET usually leads you down a path of 'Use TypeMock to test'. Following a path where there is only one testing tool available doesn't seem great either.
  • Beep beep
    Beep beep over 14 years
    Pavel - do you have another tool other than TypeMock that can provide this type of testing? Testing classes built with sane designs (e.g. using static methods, new calls in code, limiting interfaces to where multiple implementations are needed, etc) are often next to impossible to test.
  • Beep beep
    Beep beep over 14 years
    I think sealed classes are great ... the problem is testing. It stinks that we have to change our entire design because of limitations in testing .NET projects. In many cases D.I. is simply a way to get around the fact that static classes/methods are hard to test.
  • Matt Grande
    Matt Grande over 14 years
    Some people might not like paying $80 a month for a test framework.
  • Mathias
    Mathias about 14 years
    I think Moles allows you to work with sealed classes - and if you have a MSDN subscription, it's free.
  • xofz
    xofz about 14 years
    I agree with Brad here. Creating a mock object implies you are testing that type's public behavior. That is, you are specifically saying, "I need the public API of this object to behave in a certain way." This behavior is independent of however said API is implemented. This means you have an already-defined (though implicit) abstraction which needs to behave a certain way. In a static type system, this must be made explicit by creating an abstract type.
  • Adam Lenda
    Adam Lenda about 14 years
    I have found a solution and posted here: dotnetmonkey.net/post/Hard-to-Moq.aspx
  • Adam Ralph
    Adam Ralph about 13 years
    AFAIK one of the main problems with these frameworks which can mock sealed classes, statics, etc. is performance. Personally I prefer to create an interface and use that in my production code, with an inheriting proxy object injected during production and a mock injected during testing.
  • chiccodoro
    chiccodoro almost 13 years
    @abyx: Unfortunately, it is not always the developer's choice whether a class is sealed or not. Take, e.g., System.Web.HttpServerUtility in ASP.NET...
  • kodefuguru
    kodefuguru about 12 years
    An alternative is Telerik JustMock. You can use the commercial edition to test legacy code then move to the free edition after interfaces and dependency injection have been implemented.
  • Jez
    Jez about 9 years
    @BryanWatts I disagree strongly with this. Sealing a class simply denies coders the opportunity to inherit the class. They might find extending it useful in a way you haven't foreseen. You don't need to worry about them somehow screwing things up; it's (probably) not your responsibility. I'd actually do away with the sealed keyword.
  • Bryan Watts
    Bryan Watts about 9 years
    @Jez: If I hadn't considered extension when writing the class, what reason is there to trust it?
  • Ben
    Ben over 8 years
    This is the only solution that makes sense and works for mocking internal Microsoft stuff without adding any extra libraries like Fakes - thank you!
  • ZZY
    ZZY over 5 years
    Strongly agree with @Jez. Happy to see the official guideline shares the same opinion: "DO NOT seal classes without having a good reason to do so. Sealing a class because you cannot think of an extensibility scenario is not a good reason." (docs.microsoft.com/en-us/dotnet/standard/design-guidelines/‌​…) To protect methods from being misused by subclass, just leave them private. Isn't it enough?
  • Mihai Bratulescu
    Mihai Bratulescu over 5 years
    too bad that page is dead
  • Viking
    Viking over 5 years
    thanks for the solution! the page is still dead though
  • Rik Schaaf
    Rik Schaaf almost 3 years
    @Beepbeep if you have control over the sealed class yourself, you can specify an interface that this sealed class implements and you can mock this interface. If you don't control the class that is sealed (e.g. it's from a library), you might want to create an adapter that delegates functionality from the sealed class. Not only will you be able to mock this adapter (or its interface), but it will also be easier to switch to a different library, if needed.
  • Rik Schaaf
    Rik Schaaf almost 3 years
    Whether or not you want to seal every class has to some extent a relation with whether or not you want to add a disclaimer to your project. If there is a strict requirement for the (usually proprietary) code to do a certain number of things and nothing more (with eye for security and preventing the use of weird machines), then it is fine to seal whenever possible. If the code is an (open source) library for general use with only a loose specification for what it is supposed to do, then don't seal all classes. And then there is everything in the middle that you can debate over.
  • GrantByrne
    GrantByrne almost 3 years
    You can find the page on wayback machine; however, don't waste your time. The post has been updated by the author saying that it didn't actually work.