C# 如何对创建另一个类的新实例的方法或构造函数进行单元测试

C# 如何对创建另一个类的新实例的方法或构造函数进行单元测试,c#,unit-testing,constructor,moq,C#,Unit Testing,Constructor,Moq,我对这个话题做了广泛的研究,还没有找到一个可靠的答案 我想测试一个构造函数。此构造函数初始化另一个类,以设置在该类的其余部分中必需的全局变量。但是,构造函数初始化的类的构造函数依赖于web会话和其他设置的变量,这些变量在任何测试运行时都没有设置。我如何正确地模拟它以确保我只是在测试构造函数 下面是要测试的构造函数: public CheckoutManager() { _orderController = new OrderController(); _orderControll

我对这个话题做了广泛的研究,还没有找到一个可靠的答案

我想测试一个构造函数。此构造函数初始化另一个类,以设置在该类的其余部分中必需的全局变量。但是,构造函数初始化的类的构造函数依赖于web会话和其他设置的变量,这些变量在任何测试运行时都没有设置。我如何正确地模拟它以确保我只是在测试构造函数

下面是要测试的构造函数:

public CheckoutManager()
{
    _orderController = new OrderController();
    _orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}
问题在于OrderController构造函数:

public OrderController()
{
    _customer = WebUserSession.Current.Profile.Customer;
    _srd = ContextManager.GetStandardRequestByCulture( CultureInfo.CurrentUICulture.Name );
    WarehouseData data = new WarehouseData();
    data.WarehouseID = 0;   // TODO: Convert the 0 warehouse to a web warehouse type

    // Grab the attention items from the session
    AttentionItems = WebUserSession.Current.OrderAttentionItems;

    // Load the shopping cart
    _cart = ShoppingCartManager.Cart;
}
以下是我尝试的测试:

[TestMethod]
public void Constructor_ExpectInstantiation()
{
    var checkoutManager = new CheckoutManager();

    Assert.IsNotNull( checkoutManager );
}
它在_customer=WebUserSession.Current.Profile.customer处爆炸;线路。你怎么用最小起订量来模拟这个?如果它不能被嘲笑,有没有一个好的解释来解释为什么?如何修改原始构造函数,使其以更易于测试的方式具有相同的功能?提前感谢。

您可以使用,这是的一种形式,来解决此类问题

不要在构造函数中实例化您的
OrderController
,而是将其作为参数传递:

public CheckoutManager(OrderController orderController)
{
    _orderController = orderController;
    _orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}
然后,您可以在类似于
Main
的方法中的某个地方手动实例化
OrderController
,也可以使用类似的库来为您完成所有接线

现在,您可以在测试中模拟接口:

[TestMethod]
public void Constructor_ExpectInstantiation()
{
    Mock<OrderController> mockOrderController = new Mock<OrderControler>();
    var checkoutManager = new CheckoutManager(mockOrderController.Object);

    Assert.IsNotNull( checkoutManager );
}
[TestMethod]
public void构造函数_ExpectInstantiation()
{
Mock mockOrderController=new Mock();
var checkoutManager=新的checkoutManager(mockOrderController.Object);
Assert.IsNotNull(checkoutManager);
}
这样,
OrderController
的构造函数将永远不会被调用(它是一个模拟),并且不会干扰您对
CheckoutManager
的测试。如果您需要测试与它的一些交互,您可以
设置
验证
使用Moq的特定方法。

您可以使用,这是的一种形式,来解决此类问题

不要在构造函数中实例化您的
OrderController
,而是将其作为参数传递:

public CheckoutManager(OrderController orderController)
{
    _orderController = orderController;
    _orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}
然后,您可以在类似于
Main
的方法中的某个地方手动实例化
OrderController
,也可以使用类似的库来为您完成所有接线

现在,您可以在测试中模拟接口:

[TestMethod]
public void Constructor_ExpectInstantiation()
{
    Mock<OrderController> mockOrderController = new Mock<OrderControler>();
    var checkoutManager = new CheckoutManager(mockOrderController.Object);

    Assert.IsNotNull( checkoutManager );
}
[TestMethod]
public void构造函数_ExpectInstantiation()
{
Mock mockOrderController=new Mock();
var checkoutManager=新的checkoutManager(mockOrderController.Object);
Assert.IsNotNull(checkoutManager);
}

这样,
OrderController
的构造函数将永远不会被调用(它是一个模拟),并且不会干扰您对
CheckoutManager
的测试。如果您需要测试与它的一些交互,您可以
设置
使用Moq验证
特定方法。

您将无法使用Moq测试此代码。你可以

  • 通过添加接受OrderController的构造函数,修改代码以使其更易于测试
  • 使用更“先进”的测试技术,如

您将无法对此代码使用Moq测试。你可以

  • 通过添加接受OrderController的构造函数,修改代码以使其更易于测试
  • 使用更“先进”的测试技术,如

考虑将构造函数中无法模拟的静态依赖项注入为参数您可以在测试框架中使用[TestInitialize]函数来设置测试运行。你是问如何做Web会话和其他事情,还是在测试之前如何初始化一些东西?考虑注入静态依赖项,你不能在构造函数中模拟为参数,你可以在测试框架中使用[测试初始化]函数来设置测试运行。你是在问如何进行web会话和其他事情,还是只是在测试前如何初始化一些东西?