2013-07-15 2 views
1

EDIT: Я играл с этим примером и теперь my question is a different one entirely.Weird error using Rhino Mocks "тип не соответствует возвращаемому значению"

Когда я запускаю этот пример:

using Rhino.Mocks; 

public interface IInterface 
{ 
    decimal GetDecimal(); 
} 

static class Util 
{ 
    public static double? DecToDouble(this IInterface input) 
    { 
     return (double) input.GetDecimal(); 
    } 
} 

class MockExample 
{ 
    public void RunThis() 
    { 
     var stubReader = MockRepository.GenerateStub<IInterface>(); 
     stubReader.Stub(sr => sr.DecToDouble()).Return(1.2); 
    } 
} 

Я получаю эту ошибку:

System.InvalidOperationException : Type 'System.Double' doesn't match the return type 'System.Decimal' for method 'IInterface.GetDecimal();'

Почему?

+0

Вы построили режим Debug или Release? –

+0

Режим UnitTesting. – mattalxndr

+0

ОК, похоже, это настраиваемая конфигурация. Включена или отключена оптимизация? –

ответ

4

Rhino Mocks может перехватывать вызовы, которые выполняются через заглушенный интерфейс. Метод расширения выше компилируется на что-то вроде:

Util.DecToDouble(sr) 

Это означает, что ваша установка/возврата в основном звучит так:

stubReader.Stub(sr => Util.DecToDouble(sr)).Return(1.2); 

Это явно не будет работать (с большинством рамок Mocking). Правильный способ добиться того, что вы хотите:

stubReader.Stub(sr => sr.GetDecimal())).Return(1.2); 

После дальнейшего исследования: Rhino Mocks внутренне соединяет метод, объявленный Ста() к стоимости, заявленной доходности() путем вызова делегата передается на Stub() и сохранение последнего примененного вызова метода. Этот сохраненный вызов метода затем подключается к возвращаемому значению. При выполнении этого Rhino Mocks внутренне проверяет, соответствует ли тип возврата сохраненного вызова типу значения. Если они не соответствуют Rhino Mocks, возникает исключение, которое вы видите. Правильный способ определить гася бы

decimal val = 1.2M; 
    stubReader.Stub(sr => sr.DecToDouble()).Return(val); 

Но это не компилируется, так как общий PARAMS типа тупикового() и Return() должен быть совместим. Таким образом, единственный способ определить stubbing - игнорировать методы расширения и только заглушить методы, определенные в интерфейсе.

+0

Я попробую это, определенно. Но ознакомьтесь с изменениями, которые я только что сделал. Заготовка статического метода работает, если я не конвертирую тип внутри метода. Интересно, почему. – mattalxndr

0

Если вы пытаетесь дразнить IInterface тогда вы гася неправильный метод:

public void RunThis() 
{ 
    var stubReader = MockRepository.GenerateStub<IInterface>(); 
    stubReader.Stub(sr => sr.GetDecimal()).Return(1.2); 
} 

Если вы пытаетесь окурок DecToDouble, вы не можете с RhinoMocks. Методы расширения скомпилированы для вызовов статических методов, которые RhinoMocks не может издеваться, потому что они связаны во время компиляции. Некоторые структуры заглушек используют низкоуровневые запросы профилировщика для перехвата статических вызовов, но у RhinoMocks нет такой возможности, о которой я знаю.

См. this question для аналогичного обсуждения.

+0

Но 'DecToDouble' является допустимым методом расширения для' IInterface', правильно? – mattalxndr

+0

Методы расширения - это действительно статические методы, которые вы не можете заглушить. Они связаны во время компиляции. –