捕获jMock中的方法参数以传递给存根实现

Jug*_*kar 11 java unit-testing mocking jmock

我希望实现以下行为.我的测试类依赖于其他一些类,我希望用jMock来模拟这种依赖.大多数方法会返回一些标准值,但有一个方法,在这里我想打个电话到存根实现,我知道我可以调用从这个方法will(...),但我想用完全相同的参数来调用的方法传递给模拟方法的.

测试

@Test
public void MyTest(){
    Mockery context = new Mockery() {
        {
            setImposteriser(ClassImposteriser.INSTANCE);
        }
    };
    IDependency mockObject = context.mock(IDependency.class);
    Expectations exp = new Expectations() {         
        {
            allowing(mockObject).methodToInvoke(????);
            will(stubMethodToBeInvokedInstead(????));
        }       
    };      
}
Run Code Online (Sandbox Code Playgroud)

接口

public interface IDependency {
    public int methodToInvoke(int arg);
}
Run Code Online (Sandbox Code Playgroud)

要改为调用的方法

public int stubMethodToBeInvokedInstead(int arg){
    return arg;
}
Run Code Online (Sandbox Code Playgroud)

那么我如何捕获传递给被模拟方法的参数,所以我可以将它们传递给存根方法呢?

编辑

再举一个例子,假设我想INameSource在下面的(C#)代码中模拟依赖关系来测试类的扬声器

public class Speaker
{
  private readonly string firstName;
  private readonly string surname;
  private INameSource nameSource ;
 public Speaker(string firstName, string surname, INameSource nameSource)
  {
    this.firstName = firstName;
    this.surname = surname;
    this.nameSource = nameSource;
  }
  public string Introduce()
  {
    string name = nameSource.CreateName(firstName, surname);
    return string.Format("Hi, my name is {0}", name);
  }
}
public interface INameSource
{
  string CreateName(string firstName, string surname);
}
Run Code Online (Sandbox Code Playgroud)

这就是如何在Rhino Mocks for C#中完成它我理解它不会像这样容易,因为Java中缺少委托

小智 21

来自Duncan的解决方案运行良好,但是甚至有一个更简单的解决方案,而无需使用自定义匹配器.只需使用传递给CustomActions调用方法的Invocation参数.在此参数中,您可以调用getParameter(long i)方法,该方法为您提供调用的值.

所以不要这样

return matcher.getLastValue();
Run Code Online (Sandbox Code Playgroud)

用这个

return (Integer) invocation.getParameter(0);
Run Code Online (Sandbox Code Playgroud)

现在你不再需要StoringMatcher了:Duncans示例现在看起来像这样

@RunWith(JMock.class)
public class Example {

  private Mockery context = new JUnit4Mockery();

  @Test
  public void Test() {

    final IDependency mockObject = context.mock(IDependency.class);

    context.checking(new Expectations() {
      {
        // No custom matcher required here
        allowing(mockObject).methodToInvoke(with(any(Integer.class)));

        // The action will return the first argument of the method invocation.
        will(new CustomAction("returns first arg") {
          @Override
          public Object invoke(Invocation invocation) throws Throwable {
            return (Integer) invocation.getParameter(0);
          }
        });
      }
    });

    Integer test1 = 1;
    Integer test2 = 1;

    // Confirm the object passed to the mocked method is returned
    Assert.assertEquals((Object) test1, mockObject.methodToInvoke(test1));
    Assert.assertEquals((Object) test2, mockObject.methodToInvoke(test2));
  }

  public interface IDependency {
    public int methodToInvoke(int arg);
  }
Run Code Online (Sandbox Code Playgroud)