C# 调用并将其用作存根或模拟是否正确?

C# 调用并将其用作存根或模拟是否正确?,c#,unit-testing,tdd,xunit.net,C#,Unit Testing,Tdd,Xunit.net,我在演示应用程序中使用手写的赝品,但我不确定我是否正确使用了模拟软件。下面是我的代码: [Fact] public void TransferFund_WithInsufficientAccountBalance_ThrowsException() { IBankAccountRepository stubRepository = new FakeBankAccountRepository(); var service = new BankAcco

我在演示应用程序中使用手写的赝品,但我不确定我是否正确使用了模拟软件。下面是我的代码:

[Fact]
    public void TransferFund_WithInsufficientAccountBalance_ThrowsException()
    {
        IBankAccountRepository stubRepository = new FakeBankAccountRepository();
        var service = new BankAccountService(stubRepository);

        const int senderAccountNo = 1, receiverAccountNo = 2;
        const decimal amountToTransfer = 400;

        Assert.Throws<Exception>(() => service.TransferFund(senderAccountNo, receiverAccountNo, amountToTransfer));
    }

    [Fact]
    public void TransferFund_WithSufficientAccountBalance_UpdatesAccounts()
    {
        var mockRepository = new FakeBankAccountRepository();
        var service = new BankAccountService(mockRepository);
        const int senderAccountNo = 1, receiverAccountNo = 2;
        const decimal amountToTransfer = 100;

        service.TransferFund(senderAccountNo, receiverAccountNo, amountToTransfer);

        mockRepository.Verify();
    }
[事实]
公共无效转让基金账户余额不足通过例外()
{
IBankAccountRepository stubRepository=新的FakeBankAccountRepository();
var服务=新的BankAccountService(stubRepository);
const int senderAccountNo=1,receiverAccountNo=2;
常量十进制数转换=400;
Assert.Throws(()=>service.TransferFund(senderAccountNo,receiverAccountNo,amountToTransfer));
}
[事实]
公共作废转移基金(含充足账户余额)更新账户()
{
var mockRepository=新的FakeBankAccountRepository();
var服务=新的BankAccountService(mockRepository);
const int senderAccountNo=1,receiverAccountNo=2;
常量十进制数转换=100;
服务.转让基金(发送方账号、接收方账号、转让金额);
mockRepository.Verify();
}
双重测试:

public class FakeBankAccountRepository : IBankAccountRepository
{
    private List<BankAccount> _list = new List<BankAccount>
    {
        new BankAccount(1, 200),
        new BankAccount(2, 400)
    };

    private int _updateCalled;

    public void Update(BankAccount bankAccount)
    {
        var account = _list.First(a => a.AccountNo == bankAccount.AccountNo);
        account.Balance = bankAccount.Balance;
        _updateCalled++;
    }

    public void Add(BankAccount bankAccount)
    {
        if (_list.FirstOrDefault(a => a.AccountNo == bankAccount.AccountNo) != null)
            throw new Exception("Account exist");

        _list.Add(bankAccount);
    }

    public BankAccount Find(int accountNo)
    {
        return _list.FirstOrDefault(a => a.AccountNo == accountNo);
    }

    public void Verify()
    {
        if (_updateCalled != 2)
        {
            throw new Xunit.Sdk.AssertException("Update called: " + _updateCalled);
        }
    }
}
公共类FakeBankAccountRepository:IBankAccountRepository
{
私有列表_List=新列表
{
新银行账户(1200),
新银行账户(2400)
};
私有int_updateCalled;
公共作废更新(银行账户银行账户)
{
var account=_list.First(a=>a.AccountNo==bankAccount.AccountNo);
account.Balance=bankAccount.Balance;
_updateCalled++;
}
公共作废添加(银行账户银行账户)
{
if(_list.FirstOrDefault(a=>a.AccountNo==bankAccount.AccountNo)!=null)
抛出新异常(“帐户存在”);
_列表。添加(银行账户);
}
公共银行帐户查找(int accountNo)
{
返回_list.FirstOrDefault(a=>a.AccountNo==AccountNo);
}
公共无效验证()
{
如果(_updateCalled!=2)
{
抛出新的Xunit.Sdk.AssertException(“更新调用:”+\u updateCalled);
}
}
}

第二个测试实例化这个伪对象并将其称为mock,然后调用verify方法。这种方法是对的还是错的?

模拟框架就是这样工作的

  • 您可以对组件之间的交互进行假设(通常通过各种
    Expect
    -族方法进行),然后
    验证它们(您的第二次测试)
  • 或者您告诉您的测试替身以某种方式(
    存根
    设置
    )进行操作,因为它在流程中是必需的(您的第一次测试)

这种方法是正确的,但它正在重新发明轮子。除非你有很好的理由这样做,否则我会花一些时间学习和使用一种模拟框架(或者我会想到)。

@peter如果你对存根和模拟之间的区别感兴趣,从经典意义上说,你有一个模拟。具有讽刺意味的是,大多数mock框架(我特别了解Moq)都会帮助创建存根,尽管它们称之为mock。请看这两个术语之间的详细对比。我知道它们的区别。我可以使用框架轻松创建这些