Foq icon indicating copy to clipboard operation
Foq copied to clipboard

[Bug?] Cannot mock class with protected virtual method.

Open voroninp opened this issue 5 years ago • 1 comments

Description

I want to mock behaviour of HttpMessageHandler, but cannot do it because of exceptions thrown by Foq.

Is Strict mode I get NotImplementedException and in Loose mode I get NullReferenceException

Repro steps

open System
open System.Net.Http
open Foq
open System.Threading
open System.Threading.Tasks
open System.Reflection
open System.Linq

[<AbstractClass>]
type TestHandler() = 
    inherit HttpMessageHandler()
    abstract member MockableSendAsync: HttpRequestMessage * CancellationToken -> Task<HttpResponseMessage>
    override this.SendAsync(request, cancellationToken) = this.MockableSendAsync(request, cancellationToken)
    
type TestHandler2() = 
    inherit TestHandler()
    override this.MockableSendAsync(request, token) = Task.FromResult(null)
 
let handler = 
        Mock<TestHandler2>(MockMode.Strict)
            .Setup(fun h -> <@ h.MockableSendAsync(any(), any()) @>)
            .Returns(Task.FromResult(null))
            .Create()

let method = 
        typeof<TestHandler2>
            .GetMethods(BindingFlags.NonPublic ||| BindingFlags.Instance ||| BindingFlags.Public)
            .Single(fun x -> x.Name = "SendAsync")

let p = [|null; box CancellationToken.None|]
let result = method.Invoke(handler, p) :?> Task<HttpResponseMessage>
result.Result

Expected behaviour

It should jus work, I assume =) I've discovered this does not work with Moq as well.

Related information

  • Operating system: Win 10 x64
  • Foq v. 1.8.0
  • .NET Runtime: .net core 3.1.101

voroninp avatar Mar 14 '20 13:03 voroninp

Pay attention to this comment

voroninp avatar Mar 14 '20 13:03 voroninp