C# 如何模拟在方法内创建的变量-Moq

C# 如何模拟在方法内创建的变量-Moq,c#,unit-testing,mocking,tdd,moq,C#,Unit Testing,Mocking,Tdd,Moq,在这里,我想模拟discount.GetDiscount()调用,因为它进行服务调用。我不想在这个方法之外公开这个discount对象。正如您所发现的,在一个方法中有一个new语句会使它很难进行单元测试。在这种情况下通常要做的事情是像这样将依赖项注入到类中 正如Mark在评论中指出的那样,您不能只模拟折扣,因为您不能有两个同名的类。因此,您可以做的是创建一个接口,定义折扣的功能。然后您的realDiscount类和您的mock都可以实现该接口 在MyClass类中,您依赖于接口而不是类 Clas

在这里,我想模拟discount.GetDiscount()调用,因为它进行服务调用。我不想在这个方法之外公开这个discount对象。

正如您所发现的,在一个方法中有一个
new
语句会使它很难进行单元测试。在这种情况下通常要做的事情是像这样将依赖项注入到类中

正如Mark在评论中指出的那样,您不能只模拟
折扣
,因为您不能有两个同名的类。因此,您可以做的是创建一个接口,定义
折扣的功能。然后您的real
Discount
类和您的mock都可以实现该接口

MyClass
类中,您依赖于接口而不是类

Class Myclass
{
   public void CalculateShippingCost()
 {
    /// Some line of codes.

     var discount= new Discount();
     discount.GetDiscount();
     
      /// Some other functionality 
  }
}
通过这种方式,您可以创建
idiscont
接口的模拟,并在实例化时将其传递给
MyClass


如果您有少量的类,那么您可以手动执行此依赖项注入。如果你有很多类,你可以考虑使用一个DI容器来处理它。正如你发现的,在一个方法中有一个<代码>新的< /代码>语句使得很难对它进行单元测试。在这种情况下通常要做的事情是像这样将依赖项注入到类中

正如Mark在评论中指出的那样,您不能只模拟
折扣
,因为您不能有两个同名的类。因此,您可以做的是创建一个接口,定义
折扣的功能。然后您的real
Discount
类和您的mock都可以实现该接口

MyClass
类中,您依赖于接口而不是类

Class Myclass
{
   public void CalculateShippingCost()
 {
    /// Some line of codes.

     var discount= new Discount();
     discount.GetDiscount();
     
      /// Some other functionality 
  }
}
通过这种方式,您可以创建
idiscont
接口的模拟,并在实例化时将其传递给
MyClass

如果您有少量的类,那么您可以手动执行此依赖项注入。如果你有很多类,你可以考虑使用一个DI容器来处理它。 如何模拟在方法内部创建的变量

据我所知,你不能。在方法内声明的变量仅存在于该方法内,因此无法在方法外影响/操作该变量

也就是说,有一些方法可以实现您想要的,同时仍然遵循依赖注入实践

以下是我个人将采取的步骤:

  • 折扣创建一个界面(如果您还没有这样做的话)。我们把这个叫做
    idiscont
  • 创建一个能够生产
    IDiscont
    的工厂。它的界面可以如下所示:
  • (很抱歉,由于某些原因,代码示例布局为我搭建,无法运行。编辑:如果我对其进行注释,则至少它也会对代码进行格式化)

  • 将此工厂注入到类中,将其存储在
    私有只读
    变量中,并在您可以调用的
    CalculateShippingCost
    方法中:
    var discount=\u discountFactory.CreateDiscount()
  • 这样,实际的
    折扣
    仅在您的方法中使用,但您仍然可以模拟
    IDiscountFactory
    (因此它产生的
    IDiscount

    如何模拟在方法内部创建的变量

    据我所知,你不能。在方法内声明的变量仅存在于该方法内,因此无法在方法外影响/操作该变量

    也就是说,有一些方法可以实现您想要的,同时仍然遵循依赖注入实践

    以下是我个人将采取的步骤:

  • 折扣创建一个界面(如果您还没有这样做的话)。我们把这个叫做
    idiscont
  • 创建一个能够生产
    IDiscont
    的工厂。它的界面可以如下所示:
  • (很抱歉,由于某些原因,代码示例布局为我搭建,无法运行。编辑:如果我对其进行注释,则至少它也会对代码进行格式化)

  • 将此工厂注入到类中,将其存储在
    私有只读
    变量中,并在您可以调用的
    CalculateShippingCost
    方法中:
    var discount=\u discountFactory.CreateDiscount()

  • 通过这种方式,实际的
    折扣
    仅在您的方法中使用,但您仍然可以模拟
    IDiscountFactory
    (因此它产生的
    IDiscount

    这只能在
    get折扣
    方法是
    virtual
    的情况下工作,而在C中,它不是默认情况下。@MarkSeemann谢谢,Mark。你说得对。我已经更新了我的答案,改为依赖于一个接口。这只能在
    GetDiscount
    方法是
    virtual
    时起作用,而在C#中,默认情况下不是这样。@MarkSeemann谢谢你,Mark。你说得对。我已经更新了我的答案,改为依赖于接口。
    public interface IDiscountFactory
    {
       IDiscount CreateDiscount();
    }