2012-02-10 2 views
1

Я был очень доволен Moq, пока не потребовался тест метода, который принимает делегат как параметр и получил UnsupportedException. Выпуск также упоминается here и на Moq issue list.Mocking framework, который поддерживает издевательство метода с делегатом как параметр

Есть ли какие-либо фреймворки, поддерживающие этот вид насмешек?

Например:

/// 
/// 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); 
+0

Действительно ли это настоящий код или просто фрагменты образца? Я спрашиваю, потому что он не выглядит полностью указанным. Например, когда вы создаете свой макет, не должно быть другого уровня дженериков? 'new Mock >'? –

+0

Ах да, спасибо за исправление. Это была не копия, а ошибка. – henginy

+0

В вашей установочной строке вы передаете выражение (service => service.Calculate()). Вам нужно передать somthing, который разрешает делегат, такой как объект Func <>. – IanNorton

ответ

3

Я не совсем уверен, что вы пытаетесь сделать, но это компилируется и работает, используя свои интерфейсы с 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 

Смотрите также this answer для более сложного случая ,

+0

Спасибо, однако этот будет настраивать макет для любого вызова метода в UseService, тогда как я пытаюсь выбрать конкретный. Я скоро проверю ответ в ссылке. – henginy

+0

Связанный ответ, вероятно, даст вам то, что вы хотите. Я бы предупредил, что вы хотите протестировать одну вещь за раз, что обычно означает, что ваши макеты и заглушки просты. Чем сложнее вы их делаете, тем больше вы проверяете свои макеты. – TrueWill

0

Посмотрите родинок. Он поддерживает делегатов как mocks.

Moles

1

Недавно я столкнулся с этой проблемой, и вот как использовать moq (v4.0.10827) для проверки правильного метода и параметров. (Подсказка: вам нужны два слоя макетов.)

//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(); 
+0

Это интересно! Спасибо, я попробую. – henginy

Смежные вопросы