C# 嘲弄与单身

C# 嘲弄与单身,c#,testing,mocking,C#,Testing,Mocking,我目前正在做一个更大的C项目。我已经编写了几个连接到数据库层的类,现在必须对它们进行测试。使用的测试框架是VisualStudioUltimate。我已经得到了一个模拟层进行测试,但我不确定如何使用它 基本上,我的方法是这样工作的: public static void bla() { //This is a multithreaded singleton Connection con = Connection.Instance; //This raises a lot of Events

我目前正在做一个更大的C项目。我已经编写了几个连接到数据库层的类,现在必须对它们进行测试。使用的测试框架是VisualStudioUltimate。我已经得到了一个模拟层进行测试,但我不确定如何使用它

基本上,我的方法是这样工作的:

public static void bla()
{
//This is a multithreaded singleton
Connection con = Connection.Instance;

//This raises a lot of Events 
con.SomeConnection.Send(new GetBla()); 
}
interface IMyRepository
{
   void Send(Bla bla);
}

MockLayer基本上是ConnectionMock,并将其所有方法实现为mock。有没有任何方法可以使con成为Mock而不改变任何方法?

简言之,没有,没有任何方法。这是使用静态类和单例对象的最大缺点之一。您定义了一个规则,即只有一个连接对象可以存在,并且它必须始终是您指定的确切实例。创建一个mock并试图让所有代码都使用它将违反该规则

换句话说,为了模拟一个对象,您必须能够创建另一个实例并用您的实例替换期望的实例。静态类(和单例)显式地阻止了这一点


更好的选择是使用依赖项注入,这样您的“预期”连接类总是在真实环境中注册,而您的模拟总是为单元测试注册。

简而言之,不,没有办法。这是使用静态类和单例对象的最大缺点之一。您定义了一个规则,即只有一个连接对象可以存在,并且它必须始终是您指定的确切实例。创建一个mock并试图让所有代码都使用它将违反该规则

换句话说,为了模拟一个对象,您必须能够创建另一个实例并用您的实例替换期望的实例。静态类(和单例)显式地阻止了这一点


更好的选择是使用依赖项注入,这样您的“预期”连接类总是在真实环境中注册,而您的模拟总是为单元测试注册。

第一步是确定您想要做什么。。。最重要的是确定你的SUT(受试者)

有没有什么方法可以使con成为模拟的,而不改变任何方法

我不认为你能做这样的事情,即使你能找到一个技术方法来做,也不会被推荐。相反,您应该使用存储库(例如)对DAL层进行抽象。大概是这样的:

public static void bla()
{
//This is a multithreaded singleton
Connection con = Connection.Instance;

//This raises a lot of Events 
con.SomeConnection.Send(new GetBla()); 
}
interface IMyRepository
{
   void Send(Bla bla);
}
现在您可以在类中使用DI来注入对该接口的引用。当您想要编写单元测试时,您应该创建一个接口的模拟

为了轻松创建模拟,我可以向您推荐以下工具:

无论如何,在您的情况下,在不更改代码的情况下测试代码的唯一方法是将连接字符串更改为虚拟数据库,并运行集成测试

遗憾的是,我不得不告诉您,您的代码不是测试友好的,您应该重构代码以删除静态成员

我能告诉你的最好的提示是:阅读关于编写干净的测试友好代码的指南

请查看以下链接:

您对为代码编写测试感兴趣是件好事,但由于您没有参加TDD(这意味着首先编写测试),因此您在编写代码时没有考虑可测试性,结果很简单:编写测试将是一个真正的PITA,编写测试将需要重构代码


我知道您不想重构代码,因为您不想破坏现有功能,这是从一开始编写测试的最大好处之一,您可以重构代码并运行测试,以确保没有破坏任何功能。第一步是确定您想要做什么。。。最重要的是确定你的SUT(受试者)

有没有什么方法可以使con成为模拟的,而不改变任何方法

我不认为你能做这样的事情,即使你能找到一个技术方法来做,也不会被推荐。相反,您应该使用存储库(例如)对DAL层进行抽象。大概是这样的:

public static void bla()
{
//This is a multithreaded singleton
Connection con = Connection.Instance;

//This raises a lot of Events 
con.SomeConnection.Send(new GetBla()); 
}
interface IMyRepository
{
   void Send(Bla bla);
}
现在您可以在类中使用DI来注入对该接口的引用。当您想要编写单元测试时,您应该创建一个接口的模拟

为了轻松创建模拟,我可以向您推荐以下工具:

无论如何,在您的情况下,在不更改代码的情况下测试代码的唯一方法是将连接字符串更改为虚拟数据库,并运行集成测试

遗憾的是,我不得不告诉您,您的代码不是测试友好的,您应该重构代码以删除静态成员

我能告诉你的最好的提示是:阅读关于编写干净的测试友好代码的指南

请查看以下链接:

您对为代码编写测试感兴趣是件好事,但由于您没有参加TDD(这意味着首先编写测试),因此您在编写代码时没有考虑可测试性,结果很简单:编写测试将是一个真正的PITA,编写测试将需要重构代码


我知道您不想重构代码,因为您不想破坏现有的功能,这是从一开始编写测试的最大好处之一,您可以重构代码并运行测试,以确保没有破坏任何东西。实际上,您可以使用反射模拟单例。见我对以下问题的答复:


实际上,您可以使用反射模拟单例。见我对以下问题的答复: