调用方法时模拟局部变量
本文关键字:局部变量 模拟 方法 调用 | 更新日期: 2023-09-27 18:16:49
我在类的方法中模拟局部变量时遇到了一些麻烦。
我试图模拟我的工人类,但它调用一个方法,返回null值,我的上下文变量变为null。因此,当我尝试获取Name属性时,会得到一个异常。
如何强制CreateWorkerContext()
返回模拟值?可能有一种方法来模拟一个局部变量(context
)?
谢谢!
我的代码将告诉更多关于这个问题的信息:
namespace Moq
{
class Program
{
static void Main(string[] args)
{
var workerMock = new Mock<Worker>();
workerMock.Object.GetContextName();
}
}
public class Worker
{
public string GetContextName()
{
// something happens and context does not create (imitated situation)
WorkerContext context = CreateWorkerContext();
// exception because _context is null
return context.Name;
}
private WorkerContext CreateWorkerContext()
{
// imitate that context is not created
return null;
}
}
public class WorkerContext
{
public string Name { get; set; }
}
}
这里有几点值得商榷。
首先, -但这只是我的意见-您应该避免部分模拟(部分模拟=模拟不实现接口的抽象类,因此保留未被模拟的方法的原始实现)。最好是有一个Worker
可以实现的IWorker
接口。
秒 -我会创建严格的模拟。松散模拟似乎是一个很好的快捷方式,但通常会让您的方法和属性在您不打算返回默认值时返回默认值(在您的示例中为null
)
第三 -我会注射WorkerContext
。如果你不能注入它,因为你需要用。ctor参数来参数化它,那么注入一个WorkerContextFactory
,它将允许你模拟WorkerContext
像Moq这样的动态模拟库通常不是魔法。它们只能代替你自己可以用代码代替的行为。
在这个特殊的例子中,Moq不能代替CreateWorkerContext
,因为它是一个私有方法。
一个选项是将其设置为virtual
:
public class Worker
{
public string GetContextName()
{
WorkerContext context = CreateWorkerContext();
return context.Name;
}
public virtual WorkerContext CreateWorkerContext()
{
return new WorkerContext();
}
}
另一个选择是将CreateWorkerContext
方法替换为策略:
public class Worker
{
private readonly IWorkerContextFactory factory;
public Worker(IWorkerContextFactory factory)
{
if (factory == null)
throw new ArgumentNullException(nameof(factory));
this.factory = factory;
}
public string GetContextName()
{
WorkerContext context = this.factory.Create();
return context.Name;
}
}
这两个选项都将使Moq能够模拟所需的行为。