Как я могу использовать Rhino Mocks для проверки того, какие значения были переданы методу

Я новичок в насмешках, и мне сложно решить проблему с UnitTesting.

Скажем, у меня есть этот код:

public class myClass{

    private IDoStuff _doer;

    public myClass(IDoStuff doer){
        _doer = doer;
    }

    public void Go(SomeClass object){

        //do some crazy stuff to the object

        _doer.DoStuff(object) //this method is  void too
    }
}

Хорошо, поэтому я хочу UNIT test метод Go. Мне все равно, что объект _doer делает с объектом один раз, получает его.

ОДНАКО, я хочу проверить, что получил объект _doer.

в коде PSEUDO Я хочу достичь этого:

[Test]
public void MyTest()
{
    IDoStuff doer = Mocker.Mock<IDoStuff>();
    Guid id = Guid.NewGuid();

    //test Go method
    new MyClass(doer).Go(new SomeClass(){id = id});

    Assert.AreEqual(id,MockingFramework.Method(DoStuff).GetReceived<SomeClass>().id);
}

Возможно ли это с использованием Rhino, и если да, то как мне его достичь?

веселит

Ответ 1

С новым синтаксисом Arrange/Act/Assert:

[Test]
public void MyTest()
{
    // arrange
    IDoStuff doer = MockRepository.GenerateStub<IDoStuff>();
    MyClass myClass = new Myclass(doer);
    Guid id = Guid.NewGuid();

    // act
    myClass.Go(new SomeClass(){id = id});

    // assert
    doer.AssertWasCalled(x => x.DoStuff(
        Arg<Someclass>.Matches(y => y.id == id)));
}

Ответ 2

Все эти ответы предоставляют различные способы делать то, что вы хотите, и все они работают. Есть еще одна вещь, о которой нужно знать. Если вам нужно получить действительно "низкий уровень" и проверить аргументы, переданные на любой метод stubbed/mocked, вы можете использовать GetArgumentsForCallsMadeOn.

Это немного грязно, поскольку он возвращает объект [] []. Вы используете его так (предполагая, что вы tubbed stubber.InsertData принимаете значение null):

var args = stubber.GetArgumentsForCallsMadeOn(s => s.InsertData(null));

args [0] - это массив параметров, переданных в InsertData при первом вызове.

args [1] - это массив параметров, переданных в InsertData во второй раз, когда он был вызван.

и т.д...

Итак, если вы хотите увидеть целочисленное значение, переданное как второй параметр первого вызова некоторого метода, вы могли бы:

var check = (int) args[0][1];

Опять же, я бы порекомендовал один из предыдущих методов, но это доступно, если вам нужно по-настоящему разобраться и испортить аргументы.

Ответ 3

Я думаю, что у вас есть хорошо, так оно и будет:

IDoStuff doer = MockRepository.GenerateMock<IDoStuff>();

затем настройте ожидание с помощью:

doer.Expect(() => DoStuff(id));

затем в конце:

doer.VerifyAllExpectations();

EDITED из Ли отвечает, чтобы отметить, что вы также можете делать такие вещи, как:

doer.Expect(d => d.DoStuff(Arg<int>.Is.GreaterThan(5))

или

doer.Expect(d => d.DoStuff(Arg<CustomObject>.Matches(x => x.CustomProperty == "Beef")));

или аналогичные тесты, если вам не нужны точные сравнительные сравнения с использованием объектов Arg и Arg.

Ответ 4

Только предложение:

Оба решения из Wim Coenen и Патрик Стил правильно, но для первого решения очень быстро, когда есть только один параметр, появляется сообщение об ошибке при неудачном завершении теста.

Это сообщение для моей функции с двумя параметрами:

IProductChecker.MustPublish(равный 2, равный 123X); Ожидаемое # 1, фактическое # 0.

Теперь, какой из двух параметров неверен? А как насчет параметров больше?

Я подготовил тест с помощью этого кода:

//ARRANGE
const string CLASSCODE = "ABC";
const string SUBCLASSCODE = "123X";
var expected = new [] {CLASSCODE, SUBCLASSCODE};

//ACT
SUT.CallMyFunction(chkMock);
var actual = chkMock.GetArgumentsForCallsMadeOn(m => m.MustPublish(null, null))[0];

//Assert
CollectionAssert.AreEqual(expected, actual);
//instead of
//chkMock.AssertWasCalled(m => m.MustPublish(Arg<string>.Is.Equal("2"), Arg<string>.Is.Equal(SUBCLASSCODE)));

Итак, в этом случае сообщение:

Ошибка CollectionAssert.AreEqual. (Элемент с индексом 0 не совпадает.)

Hi

Ответ 5

Если вы просто хотите проверить, что экземпляр MyClass передает свой параметр в doer.Go, вы можете просто настроить ожидание:

SomeClass obj = new SomeClass { id = id };

doer.Expect(d => d.DoStuff(obj));

//test go method
new MyClass(doer).Go(obj);

doer.VerifyAllExpectations();

Однако, если вы хотите проверить, что он передает какой-то, возможно, другой объект с определенным значением для свойства, вы можете использовать ограничение:

doer.Expect(d => d.DoStuff(null))
    .IgnoreArguments()
    .Constraints(Property.Value("Id", expectedId));