如何假冒行动<>与FakeItEasy

时间:2013-11-14 09:35:15

标签: c# unit-testing mocking action fakeiteasy

我正在使用FakeItEasy库为我的单元测试创​​建假货。

我有ClassUnderTest我要测试方法MethodToTest(Data dataObject)。这个方法调用一个我想虚假的接口方法:

public interface IFoo
{
  void Execute(Action<IDataAccess> action);
}

public class ClassUnderTest
{
  private IFoo _foo;

  public ClassUnderTest(IFoo foo)
  {
    _foo = foo;
  }

  public void MethodToTest(Data dataObject)
  {
    _foo.Execute(dataAccess => dataAccess.Update(dataObject));
  }
}

public interface IDataAccess
{
  void Update(Data data);
}

public class Data
{
  public int Property { get; set; }
}

在我的单元测试中,我想检查测试方法是否正确调用接口(具有正确的属性值):

[TestClass]
public class UnitTest1
{
  [TestMethod]
  public void TestMethod1()
  {
    var foo = A.Fake<IFoo>(x => x.Strict());
    A.CallTo(() => foo.Execute(dataAccess => dataAccess.Update(A<Data>.That.Matches(d => d.Property == 20))));      

    var cut = new ClassUnderTest(foo);

    cut.MethodToTest(new Data { Property = 20 });      
  }
}

但在此测试中配置错误。我得到了例外:

  

测试方法TestProject1.UnitTest1.TestMethod1抛出异常:   FakeItEasy.ExpectationException:调用严格伪造的非配置方法“Execute”。

有人知道我必须如何正确配置CallTo()语句吗?

提前致谢!

2 个答案:

答案 0 :(得分:4)

更新的例子确实有帮助,@ rhe1980。

首先说明您提供的测试:

  1. A.CallTo方法没有做任何事情 - 它没有设置行为(使用.Invokes.Returns甚至是.DoesNothing)或验证方法已被调用(例如.MustHaveHappened)。
  2. 比较Action似乎很难。我确实在Compare Delegates Action<T>找到了一些建议,但如果是我,我会采取稍微不同的方法。
  3. 我没有尝试将Action委托与参考模型进行比较,而是认为我可以通过捕获提供给Execute的操作然后在IDataAccess上运行它来模拟这一点,然后看看行动的作用。幸运的是,我们有FakeItEasy来帮助解决这个问题!

    我在这次测试中取得了成功:

    [TestMethod]
    public void TestMethod1()
    {
        // Arrange
        var foo = A.Fake<IFoo>(x => x.Strict());
    
        var fakeDataAccess = A.Fake<IDataAccess>();
    
        A.CallTo(() => foo.Execute(A<Action<IDataAccess>>.Ignored))
                        .Invokes((Action<IDataAccess> action)=>action(fakeDataAccess));
    
        var cut = new ClassUnderTest(foo);
    
        // Act
        cut.MethodToTest(new Data { Property = 20 });
    
        // Assert
        A.CallTo(() => fakeDataAccess.Update(A<Data>.That.Matches(d => d.Property == 20)))
            .MustHaveHappened();
    }
    

    我希望它有所帮助。

答案 1 :(得分:1)

如果我理解你的意图,你需要使用如下内容:

A.CallTo(() => foo.Execute(A<Action<IDataAccess>>.Ignored).MustHaveHappened();