[英]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
Setup
和Verify
特定方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.