Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 单元测试接口存储库的目的是什么_C#_Unit Testing_Tdd_Rhino Mocks - Fatal编程技术网

C# 单元测试接口存储库的目的是什么

C# 单元测试接口存储库的目的是什么,c#,unit-testing,tdd,rhino-mocks,C#,Unit Testing,Tdd,Rhino Mocks,我正在对一个icCustomerRepository接口进行单元测试,该接口用于检索Customer类型的对象 作为单元测试,通过以这种方式测试icCustomerRepository,我获得了什么价值 以下测试在什么情况下会失败 对于这种性质的测试,是否建议进行我知道应该失败的测试?i、 e.当我知道我只在存储库中放置了5时,查找id4 我可能遗漏了一些明显的东西,但实现icCustomerRepository的类的集成测试似乎更有价值 [TestClass] public class C

我正在对一个
icCustomerRepository
接口进行单元测试,该接口用于检索
Customer
类型的对象

  • 作为单元测试,通过以这种方式测试
    icCustomerRepository
    ,我获得了什么价值
  • 以下测试在什么情况下会失败
  • 对于这种性质的测试,是否建议进行我知道应该失败的测试?i、 e.当我知道我只在存储库中放置了
    5
    时,查找id
    4
我可能遗漏了一些明显的东西,但实现
icCustomerRepository
的类的集成测试似乎更有价值

[TestClass]
public class CustomerTests : TestClassBase
{
    private Customer SetUpCustomerForRepository()
    {
        return new Customer()
        {
            CustId = 5,
            DifId = "55",
            CustLookupName = "The Dude",
            LoginList = new[]
            {
                new Login { LoginCustId = 5, LoginName = "tdude" },
                new Login { LoginCustId = 5, LoginName = "tdude2" }
            }
        };
    }

    [TestMethod]
    public void CanGetCustomerById()
    {
        // arrange
        var customer = SetUpCustomerForRepository();
        var repository = Stub<ICustomerRepository>();

        // act
        repository.Stub(rep => rep.GetById(5)).Return(customer);

        // assert
        Assert.AreEqual(customer, repository.GetById(5));
    }
}
[TestClass]
公共类CustomerTests:TestClassBase
{
私人客户设置CustomerForrepository()
{
返回新客户()
{
CustId=5,
defid=“55”,
CustLookupName=“这家伙”,
LoginList=new[]
{
新登录名{LoginCustId=5,LoginName=“tdude”},
新登录名{LoginCustId=5,LoginName=“tdude2”}
}
};
}
[测试方法]
公共无效CanGetCustomerById()
{
//安排
var customer=SetUpCustomerForRepository();
var repository=Stub();
//表演
repository.Stub(rep=>rep.GetById(5)).Return(customer);
//断言
AreEqual(customer、repository.GetById(5));
}
}
测试基类

public class TestClassBase
{
    protected T Stub<T>() where T : class
    {
        return MockRepository.GenerateStub<T>();
    }
}
公共类TestClassBase
{
受保护的T存根(),其中T:class
{
返回MockRepository.GenerateStub();
}
}
ICustomerRepository和IRepository

public interface ICustomerRepository : IRepository<Customer>
{
    IList<Customer> FindCustomers(string q);
    Customer GetCustomerByDifID(string difId);
    Customer GetCustomerByLogin(string loginName);
}

public interface IRepository<T>
{
    void Save(T entity);
    void Save(List<T> entity);
    bool Save(T entity, out string message);
    void Delete(T entity);
    T GetById(int id);
    ICollection<T> FindAll();
}
公共接口ICCustomerRepository:IRepository
{
IList FindCustomers(字符串q);
Customer GetCustomerByDifID(字符串difId);
客户GetCustomerByLogin(字符串登录名);
}
公共接口假定
{
无效保存(T实体);
作废保存(列表实体);
bool保存(T实体,输出字符串消息);
无效删除(T实体);
T GetById(int-id);
i收集FindAll();
}

根据定义,接口只是契约,因此没有代码可供测试。您希望针对接口的具体实现编写单元测试,因为实际执行代码就存在于此


如果接口没有具体的实现,而您只是在模拟一个具体的实现,那么您的单元测试只是基于一个模拟。这真的没有多大价值。

我可能遗漏了一些东西,但似乎测试的每个方面都是模拟的

一般来说,您只模拟不是测试核心的对象。在这种情况下,您可以使用此存储库作为一个函数的源,您希望使用该存储库来检索customer#5并对其执行操作


例如,您可以模拟客户存储库,以便调用验证用户登录的方法。您使用模拟存储库是为了防止单元测试依赖真实数据源,而不是为了测试模拟存储库。

您的测试对我来说毫无意义。您正在测试预编程存根是否返回您提供给它的值,而不是测试任何实际代码

遵循dcp的回复。接口是方法的声明。您应该测试这些功能的实现。

测试规则#1:

在编写测试之前,请先了解测试的目的以及它试图证明的内容。如果你不知道它证明了什么,那么它是无用的:)

正如其他海报所正确指出的,您正在存根一个接口,然后调用存根——这并不能证明您的生产代码是否工作

什么是存根?

存根用于提供固定值,以驱动被测类的某些方面。例如,假设您有一个
CustomerService
,其实例类型为
ICCustomerRepository
。如果您希望看到
CustomerService
能够在存储库为空时优雅地处理错误情况,您可以将
iccustomerrepository
GetCustomerById
方法存根为nothing/null/抛出异常,然后确保
CustomerService
方法执行了正确的操作(例如,返回未找到客户的结果)

也就是说,存根只是帮助您达到特定条件/行为的合作者。我们正在测试
CustomerService
,存根
ICCustomerRepository
仅帮助我们实现目标


你不是第一个问这个问题的人:)。我通常建议开发人员这样做。它有助于理解所有的交互以及框架实际上为您做了什么

怎么做?无论我读到哪里,我们都被教导为单元测试模拟接口。我们如何对具体的实现进行单元测试?据我所知,我认为应该避免这样做。你能举个例子吗?非常感谢。接口是一种规范、一种声明,而不是您可以运行(从而测试)的代码。您可以在具体的类中实现该规范,这就是您将要运行和测试的代码。您可以使用模拟来实现接口,以帮助您测试依赖于实现该接口的对象的其他代码。你不是“测试一个接口”,而是通过调用这些实现上的接口方法来测试该接口的实现是否正确(“针对接口进行测试”)。愚蠢的例子:一个
Eater
接口,用于
eat
,由
Dog
实现,并由
提要中的
Master
调用(食客宠物)
方法。当您测试
Dog
时,您将通过在狗实例上调用
eat
来测试
Eater
接口的实现,并查看例如狗的体重增加。当您测试
Master
s
feed()
方法时,您将创建