简体   繁体   English

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

[英]How to unit test a method or constructor which creates a new instance of another class

I've done extensive research on this topic and have yet to find a reliable answer so here goes. 我已经对该主题进行了广泛的研究,但仍未找到可靠的答案。

I have a constructor I'd like to test. 我有一个要测试的构造函数。 This constructor initializes another class in order to set a global variable which is necessary throughout the rest of the class. 此构造函数初始化另一个类,以设置一个全局变量,该变量在该类的其余部分中都是必需的。 However, the constructor of the class which the constructor initializes has dependencies on things like web session and other variables being set which are not set when the any tests run. 但是,构造函数初始化的类的构造函数依赖于诸如Web会话之类的东西以及其他变量的设置,而这些变量在运行任何测试时都不会设置。 How can I properly mock this to make sure I'm just testing the constructor? 我如何正确地模拟它以确保我只是在测试构造函数?

Here's the constructor to be tested: 这是要测试的构造函数:

public CheckoutManager()
{
    _orderController = new OrderController();
    _orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}

The problem lies in the OrderController constructor: 问题出在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;
}

Here is my attempted test: 这是我尝试的测试:

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

    Assert.IsNotNull( checkoutManager );
}

It bombs out at the _customer = WebUserSession.Current.Profile.Customer; 它在_customer = WebUserSession.Current.Profile.Customer;轰炸 line. 线。 How do you mock this using Moq? 您如何使用Moq来模拟呢? If it cannot be mocked, is there a good explanation as to why? 如果不能嘲笑,为什么有很好的解释? How could the original constructor be modified to have the same functionality in a more testable way? 如何将原始构造函数修改为具有可测试性的相同功能? Thank you in advance. 先感谢您。

You can use Dependency Injection , which is a form of Inversion of Control , to solve these kind of problems. 您可以使用“ Dependency Injection (这是控制反转的一种形式)来解决此类问题。

Instead of instantiating your OrderController in the constructor, pass it as an argument: 与其在构造函​​数中实例化OrderController ,不如将其作为参数传递:

public CheckoutManager(OrderController orderController)
{
    _orderController = orderController;
    _orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}

You can then either instantiate the OrderController either manually somewhere in a Main -like method, or with a library like Autofac which will do all the wiring for you. 然后,您既可以在OrderController Main的方法中手动实例化OrderController也可以使用类似于Autofac的库Autofac它来为您完成所有连接。

So now you can mock your interface in your test: 现在,您可以在测试中模拟您的界面:

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

    Assert.IsNotNull( checkoutManager );
}

That way, the constructor of OrderController will never be called (it's a mock) and it won't interfere with your tests of CheckoutManager . 这样,就不会调用OrderController的构造函数(这是一个模拟),并且不会干扰CheckoutManager的测试。 If you need to test some interactions with it, you can Setup and Verify specific methods using Moq. 如果需要测试与之的某些交互,则可以使用Moq SetupVerify特定方法。

You won't be able to use Moq test to this code. 您将无法对该代码使用Moq测试。 You could 你可以

  • Modify the code to make it more testable by adding a constructor that accepts an OrderController 通过添加一个接受OrderController的构造函数来修改代码,使其更具可测试性
  • Use a more "advanced" testing technique such as shims. 使用更“高级”的测试技术,例如垫片。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何对创建任务的方法进行单元测试 - How to unit testing a method which creates a task 我如何对方法正确进行单元测试以将新值分配给另一个类 - How do I unit-test that a method correctly assigns a new value to another class 如何模拟创建 object 新实例的方法 - How to mock a method that creates a new instance of an object 如何在单元测试中使用Moq调用同一类中的另一个方法 - How to use Moq in unit test that calls another method in same class 如何在MOQ的另一个类单元测试中使用模拟方法 - How to use mocked method that in another class Unit Test in MOQ 如何在 xUnit 中为 class 构造函数创建单元测试? - How to create unit test for class constructor in xUnit? 用参数创建类实例的C#中的编写方法 - Writing Method in C# Which Creates Instance Of Class Using Parameter 如何在类中为方法编写单元测试,但不使用C#中的类调用构造函数 - How to write unit test for a method in a class but not call the constructor i the class in C# 如何对创建新进程的代码进行单元测试? - How do I unit test code that creates a new Process? 如何对使用静态类的方法进行单元测试,而该静态类又使用ConfigurationElementCollection? - How to unit test a method which uses a static class which in turn uses ConfigurationElementCollection?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM