如何最小化来自工厂的方法调用
How to Moq a method calls from factory
在 Startup 中我定义了一个工厂,类似于
接口有 1 个方法 Process 如下。
//saves to db.
public interface Iprocessor
{
void Process(List<items>);
}
在 Startup.cs
中注册工厂的代码
Func<string, IProcessor> accessor = key =>
{
switch(key){
case "new":
return factory.GetService<NewProcessor>();
case "old":
return factory.GetService<OldProcessor>();
}
}
我的服务 class 使用这个工厂,我需要帮助来模拟它。
private readonly Func<string,Iprocessor> _processor;
_processor 是使用 DI 分配的。
public void ProcessRecords(List<items> items){
List<string> types = new List<string> () { "new", "old"};
foreach(var type in types)
{
var processor = _processor(type);
if(processor != null)
{
_processor.Process(items);
}
}
}
如何模拟 Process 方法调用?
为了确保一切正常,您需要分别测试每个组件。首先,您必须确保您的 OldProcessor
和 NewProcessor
按预期工作。
之后你可以关注ProcessRecords
。
如果我可以假设您的服务 class 在其 ctor:
中接收到工厂委托
class SUT
{
private readonly Func<string,Iprocessor> _processor;
public SUT(Func<string,Iprocessor> processor)
{
this._processor = processor;
}
public void ProcessRecords(List<items> items)
{
...
}
}
那么在你的情况下,你需要做的就是创建 Iprocessor
mock
并提供一个将始终解决此模拟的委托:
[Fact]
public void TestMethod1()
{
//Arrange
var processorMock = new Mock<Iprocessor>();
Func<string, Iprocessor> factory = _ => processorMock.Object;
var input = new List<items> { ... };
//Act
var sut = new SUT(factory);
sut.ProcessRecords(input);
//Assert
processorMock.Verify(processor => processor.Process(input), Times.Exactly(2));
}
然后可以验证Process
方法被调用了两次
或者,如果您愿意,可以创建两个单独的模拟:
[Fact]
public void TestMethod2()
{
//Arrange
var oldProcessorMock = new Mock<Iprocessor>();
var newProcessorMock = new Mock<Iprocessor>();
Func<string, Iprocessor> factory =
t => t == "new"
? newProcessorMock.Object
: oldProcessorMock.Objet;
var input = new List<items> { ... };
//Act
var sut = new SUT(factory);
sut.ProcessRecords(input);
//Assert
oldProcessorMock.Verify(processor => processor.Process(input), Times.Once);
newProcessorMock.Verify(processor => processor.Process(input), Times.Once);
}
更新:设置Process
方法
oldProcessorMock
.Setup(processor => processor.Process(It.IsAny<List<items>>())
.Verifiable();
newProcessorMock
.Setup(processor => processor.Process(It.IsAny<List<items>>())
.Verifiable();
在 Startup 中我定义了一个工厂,类似于
接口有 1 个方法 Process 如下。
//saves to db.
public interface Iprocessor
{
void Process(List<items>);
}
在 Startup.cs
中注册工厂的代码Func<string, IProcessor> accessor = key =>
{
switch(key){
case "new":
return factory.GetService<NewProcessor>();
case "old":
return factory.GetService<OldProcessor>();
}
}
我的服务 class 使用这个工厂,我需要帮助来模拟它。
private readonly Func<string,Iprocessor> _processor;
_processor 是使用 DI 分配的。
public void ProcessRecords(List<items> items){
List<string> types = new List<string> () { "new", "old"};
foreach(var type in types)
{
var processor = _processor(type);
if(processor != null)
{
_processor.Process(items);
}
}
}
如何模拟 Process 方法调用?
为了确保一切正常,您需要分别测试每个组件。首先,您必须确保您的 OldProcessor
和 NewProcessor
按预期工作。
之后你可以关注ProcessRecords
。
如果我可以假设您的服务 class 在其 ctor:
class SUT
{
private readonly Func<string,Iprocessor> _processor;
public SUT(Func<string,Iprocessor> processor)
{
this._processor = processor;
}
public void ProcessRecords(List<items> items)
{
...
}
}
那么在你的情况下,你需要做的就是创建 Iprocessor
mock
并提供一个将始终解决此模拟的委托:
[Fact]
public void TestMethod1()
{
//Arrange
var processorMock = new Mock<Iprocessor>();
Func<string, Iprocessor> factory = _ => processorMock.Object;
var input = new List<items> { ... };
//Act
var sut = new SUT(factory);
sut.ProcessRecords(input);
//Assert
processorMock.Verify(processor => processor.Process(input), Times.Exactly(2));
}
然后可以验证Process
方法被调用了两次
或者,如果您愿意,可以创建两个单独的模拟:
[Fact]
public void TestMethod2()
{
//Arrange
var oldProcessorMock = new Mock<Iprocessor>();
var newProcessorMock = new Mock<Iprocessor>();
Func<string, Iprocessor> factory =
t => t == "new"
? newProcessorMock.Object
: oldProcessorMock.Objet;
var input = new List<items> { ... };
//Act
var sut = new SUT(factory);
sut.ProcessRecords(input);
//Assert
oldProcessorMock.Verify(processor => processor.Process(input), Times.Once);
newProcessorMock.Verify(processor => processor.Process(input), Times.Once);
}
更新:设置Process
方法
oldProcessorMock
.Setup(processor => processor.Process(It.IsAny<List<items>>())
.Verifiable();
newProcessorMock
.Setup(processor => processor.Process(It.IsAny<List<items>>())
.Verifiable();