Why does FakeItEasy throw this exception and why does the method virtual fix it?

I have a test (code below) to verify that Method1 calls method2. The exception that I get is

The current proxy generator cannot intercept the specified method for the following reason: - Sealed methods cannot be intercepted.

The test method does not seal itself. However, it has a dependency on a sealed class (a third-party class for which I have problems creating a wrapper to mock it - is another topic for another question). In any case, at the moment I do not ask FakeItEasy to mock the sealed class. And when debugging my test, when a dependency is called, I can clearly see that a real object is being created, not a fake.

And yet, given the error message, I feel this might be related in some way.

In addition, I discovered through a random blog post that makes the method virtual, fixes the problem, allowing me to check the pass. I tried and it worked. But I don’t understand why he fixed it, and despite this, it makes no sense for me to keep the method virtual. In my case, the test class does not have its own children, i.e. there are no children to override its methods, so I see no reason to make it virtual.

Am I mistaken in thinking that I have no reason to make this method virtual?
Is FakeItEasy really trying to mock this private class?

I am really not sure how to continue this test.

My test

[SetUp] public void SetUp() { // Arrange _service2 = A.Fake<Service2>(x => x.WithArgumentsForConstructor( () => new Service2())); _service1 = A.Fake<Service1>(x => x.WithArgumentsForConstructor( () => new Service1(_service2))); } [Test] public void when_Method1_executes_it_calls_Method2() { // Act result = _service1.Method1(); // Assert A.CallTo(() => _service2.Method2()) .WithAnyArguments() .MustHaveHappened(); } 


Related Methods

 public class Service1 : IService1 { private readonly IService2 _service2; public Service1(IService2 service2) { _service2 = service2; } public bool Method1() { using (var dependency = new MyDependency()) // third party sealed class { } var x = _service2.Method2(); } } public class Service2 : IService2 { public bool Method2() // making this virtual fixes the FakeItEasy exception { } } 
+7
c # asp.net-mvc testing fakeiteasy
source share
3 answers

In normal application to the scope class, sealed in this case refers to the inability to override this method. Using sealed with a method is only permissible if the method is override , however methods that are not virtual in the first place cannot be overridden and therefore themselves implicitly sealed.

This error refers to the fact that it cannot accept methods

+19
source share

Arawola's answer is great. I urge you to accept it and / or vote for it.

However, there is a different approach. Make _service2 fake IService2 .

Then you do not need to change the signature of any methods (interface methods are always overridden / intercepted). In general, it’s easier to fake interface interfaces than concrete (or even abstract) classes, and has a good effect from actually testing that your collaboration classes can work with interfaces, and not just with specific interface implementations.

While I'm here, and this part is not really related to your error, but it can help make your code a little more understandable, since you are testing Service1 , I would not fake it; use the actual instance of Service1 . This allows readers to understand what is actually being tested. Counterfeiting the system under test is widely considered a code smell.

If you manage to take both of these points, your SetUp will look something like this:

 [SetUp] public void SetUp() { // Arrange _service2 = A.Fake<IService2>(); _service1 = new Service1(_service2); } 

And your test should pass.

+9
source share

I have been pursuing an almost identical problem for almost two days now. Blair Conrad’s decision above falsification at the interface level worked for me, and it actually makes sense:

If the class under test does not depend on another class, none of them should pass the test. Therefore, you fake an interface, not a class that implements an interface.

0
source share

All Articles