简体   繁体   中英

Mocking framework that supports mocking a method with delegate as parameter

I was very happy with Moq until I needed to test a method that takes a delegate as parameter and got an UnsupportedException. The issue is also mentioned here and on Moq issue list .

Is there any framework that supports this kind of mocking?

For example:

/// 
/// Interfaces
///

public interface IChannelFactory<T> {
    TReturn UseService<TReturn>(Func<T, TReturn> function);
}

public interface IService {
    int Calculate(int i);
}

///
/// Test
///

Mock<IChannelFactory<IService>> mock = new Mock<IChannelFactory<IService>>();

// This line results in UnsupportedException
mock.Setup(x => x.UseService(service => service.Calculate(It.IsAny<int>()))).Returns(10);

I'm not quite sure what you're trying to do, but this compiles and runs using your interfaces with Moq 4:

var mock = new Mock<IChannelFactory<IService>>();

mock.Setup(x => x.UseService(It.IsAny<Func<IService, int>>())).Returns(10);

int result = mock.Object.UseService(x => 0);

Console.WriteLine(result);  // prints 10

See also this answer for a more complex case.

I ran into this same issue recently, and here's how to use moq (v4.0.10827) to test the correct method and parameters are called. (Hint: you need two layers of mocks.)

//setup test input
int testInput = 1;
int someOutput = 10;

//Setup the service to expect a specific call with specific input
//output is irrelevant, because we won't be comparing it to anything
Mock<IService> mockService = new Mock<IService>(MockBehavior.Strict);
mockService.Setup(x => x.Calculate(testInput)).Returns(someOutput).Verifiable();

//Setup the factory to pass requests through to our mocked IService
//This uses a lambda expression in the return statement to call whatever delegate you provide on the IService mock
Mock<IChannelFactory<IService>> mockFactory = new Mock<IChannelFactory<IService>>(MockBehavior.Strict);
mockFactory.Setup(x => x.UseService(It.IsAny<Func<IService, int>>())).Returns((Func<IService, int> serviceCall) => serviceCall(mockService.Object)).Verifiable();

//Instantiate the object you're testing, and pass in the IChannelFactory
//then call whatever method that's being covered by the test
//
//var target = new object(mockFactory.Object);
//target.targetMethod(testInput);

//verifying the mocks is all that's needed for this unit test
//unless the value returned by the IService method is used for something
mockFactory.Verify();
mockService.Verify();

Have a look at Moles. It supports delegates as mocks.

Moles

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM