Как я могу использовать Rhino Mocks для проверки того, какие значения были переданы методу - PullRequest
16 голосов
/ 12 июля 2010

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

ура

Ответы [ 5 ]

23 голосов
/ 12 июля 2010

С новым синтаксисом 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)));
}
7 голосов
/ 13 июля 2010

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

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

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

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

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

и т.д ...

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

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

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

5 голосов
/ 12 июля 2010

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

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

, затем установите ожидание с помощью:

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

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

doer.VerifyAllExpectations();

РЕДАКТИРОВАНИЕ из ответов Ли, чтобы отметить, что вы также можете делать такие вещи, как:

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

или

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

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

3 голосов
/ 01 апреля 2016

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

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

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

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

1 голос
/ 12 июля 2010

Если вы просто хотите проверить, что экземпляр 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));
...