如何使用 Rhino Mocks 来检查传递给方法的值

发布于 2024-09-08 18:35:50 字数 808 浏览 2 评论 0原文

我是模拟新手,并且很难解决单元测试的问题。

假设我有这段代码:

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
    }
}

好的,所以我想对 Go 方法进行单元测试。我不关心 _doer 对象一旦获取它就会对该对象执行什么操作。

但是,我确实想检查 _doer 对象收到的内容。

在伪代码中我想实现这一点:

[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是否可以实现这一点,如果可以,我该如何实现?

干杯

I'm new to mocking, and I'm having a hard time solving an issue with UnitTesting.

Say I have this code:

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
    }
}

Ok, so I want to UNIT test the Go method. I don't care what the _doer object does to the object once is gets it.

HOWEVER, I do want to inspect what the _doer object has received.

in PSEUDO code I want to achieve this:

[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);
}

Is this possible using Rhino, and if so, how do I achieve it?

cheers

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

少钕鈤記 2024-09-15 18:35:50

使用新的 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)));
}

With the new Arrange/Act/Assert syntax:

[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)));
}
青柠芒果 2024-09-15 18:35:50

所有这些答案都提供了多种方法来完成您想做的事情,并且所有这些方法都有效。还有一件事需要注意。如果您需要真正的“低级别”并检查传递给任何存根/模拟方法的参数,您可以使用GetArgumentsForCallsMadeOn

它有点混乱,因为它返回 object[][]。您可以像这样使用它(假设您存根 stubber.InsertData 以接受 null):

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

args[0] 是第一次调用时传递给 InsertData 的参数数组。

args[1] 是第二次调用时传递给 InsertData 的参数数组。

等等...

因此,如果您想查看作为某个方法的第一次调用的第二个参数传递的整数值,您可以:

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

同样,我建议使用前面的方法之一,但是如果您需要真正了解,则可以使用此方法沮丧和肮脏地检查参数。

All of these answers provide various ways to do what you want and all of them work. There's one additional thing to be aware of. If you need to get really "low level" and check out arguments passed to any stubbed/mocked method, you can use GetArgumentsForCallsMadeOn.

It's a little messy as it returns object[][]. You use it like this (assuming you stubbed stubber.InsertData to accept null):

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

args[0] is an array of parameters passed to InsertData the first time it was called.

args[1] is an array of parameters passed to InsertData the second time it was called.

etc...

So if you wanted to see the integer value passed as the second parameter of the first invocation of some method you could:

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

Again, I'd recommend one of the previous methods, but this is available if you need to get really down and dirty to check out arguments.

生生漫 2024-09-15 18:35:50

我认为你所拥有的很好,所以它是:

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 对象进行引用比较。

I think what you have is good so it'd be:

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

then set up the expectation via:

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

then at the end:

doer.VerifyAllExpectations();

EDITED from Lee's answers to note that you can also do stuff like:

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

or

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

or similar tests when you don't want exact reference comparisons by using the Arg and Arg objects.

So尛奶瓶 2024-09-15 18:35:50

仅一个建议:

来自 Wim CoenenPatrick Steele 是正确的,但是,对于第一个解决方案,当只有一个参数时非常快,有测试失败时会出现不正确的错误消息。

这是我的函数的一条消息,带有两个参数:

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 处的元素不匹配。)

Only a suggestion:

both solution from Wim Coenen and Patrick Steele are correct but, for first solution, very fast when there is only one parameter, there are an incorrect error message when test fails.

This is a message for my function with two parameters:

IProductChecker.MustPublish(equal to 2, equal to 123X); Expected #1, Actual #0.

Now, which of the two parameters is wrong? And what about if parameters were more?

I've prepared test with this code:

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

So, in this case the message is:

CollectionAssert.AreEqual failed. (Element at index 0 do not match.)

Hi

╰つ倒转 2024-09-15 18:35:50

如果您只想测试 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));

If you just want to test that the MyClass instance passes its parameter to doer.Go then you can just set up an expectation:

SomeClass obj = new SomeClass { id = id };

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

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

doer.VerifyAllExpectations();

However if you want to check that it passes some possibly different object with some particular value for a property, then you can use a constraint:

doer.Expect(d => d.DoStuff(null))
    .IgnoreArguments()
    .Constraints(Property.Value("Id", expectedId));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文