如何对创建另一个 class 的新实例的方法或构造函数进行单元测试
How to unit test a method or constructor which creates a new instance of another class
我已经对这个主题进行了广泛的研究,但尚未找到可靠的答案,所以这里开始吧。
我有一个要测试的构造函数。此构造函数初始化另一个 class 以设置一个全局变量,该变量在整个 class 的其余部分都是必需的。但是,构造函数初始化的 class 的构造函数依赖于 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;线。你如何使用最小起订量模拟这个?如果它不能被嘲笑,是否有一个很好的解释为什么?如何以更可测试的方式修改原始构造函数以具有相同的功能?提前谢谢你。
您可以使用Dependency Injection
, which is a form of Inversion of Control来解决这类问题。
与其在构造函数中实例化您的 OrderController
,不如将其作为参数传递:
public CheckoutManager(OrderController orderController)
{
_orderController = orderController;
_orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}
然后您可以在类似 Main
的方法中手动实例化 OrderController
,或者使用像 Autofac
这样的库来为您完成所有连接。
现在您可以在测试中模拟您的界面了:
[TestMethod]
public void Constructor_ExpectInstantiation()
{
Mock<OrderController> mockOrderController = new Mock<OrderControler>();
var checkoutManager = new CheckoutManager(mockOrderController.Object);
Assert.IsNotNull( checkoutManager );
}
这样,OrderController
的构造函数将永远不会被调用(它是一个模拟)并且它不会干扰您对 CheckoutManager
的测试。如果您需要测试与它的某些交互,您可以使用 Moq Setup
和 Verify
特定方法。
您将无法对此代码使用 Moq 测试。你可以
- 通过添加接受 OrderController 的构造函数修改代码以使其更易于测试
- 使用更 "advanced" 的测试技术,例如 shims.
我已经对这个主题进行了广泛的研究,但尚未找到可靠的答案,所以这里开始吧。
我有一个要测试的构造函数。此构造函数初始化另一个 class 以设置一个全局变量,该变量在整个 class 的其余部分都是必需的。但是,构造函数初始化的 class 的构造函数依赖于 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;线。你如何使用最小起订量模拟这个?如果它不能被嘲笑,是否有一个很好的解释为什么?如何以更可测试的方式修改原始构造函数以具有相同的功能?提前谢谢你。
您可以使用Dependency Injection
, which is a form of Inversion of Control来解决这类问题。
与其在构造函数中实例化您的 OrderController
,不如将其作为参数传递:
public CheckoutManager(OrderController orderController)
{
_orderController = orderController;
_orderController.PropertyChanged += (sender, args) => NotifyPropertyChanged(args.PropertyName);
}
然后您可以在类似 Main
的方法中手动实例化 OrderController
,或者使用像 Autofac
这样的库来为您完成所有连接。
现在您可以在测试中模拟您的界面了:
[TestMethod]
public void Constructor_ExpectInstantiation()
{
Mock<OrderController> mockOrderController = new Mock<OrderControler>();
var checkoutManager = new CheckoutManager(mockOrderController.Object);
Assert.IsNotNull( checkoutManager );
}
这样,OrderController
的构造函数将永远不会被调用(它是一个模拟)并且它不会干扰您对 CheckoutManager
的测试。如果您需要测试与它的某些交互,您可以使用 Moq Setup
和 Verify
特定方法。
您将无法对此代码使用 Moq 测试。你可以
- 通过添加接受 OrderController 的构造函数修改代码以使其更易于测试
- 使用更 "advanced" 的测试技术,例如 shims.