如何使用 IGenericRepository 进行模拟
How to mock with a IGenericRepository
我是 TDD 开发的新手,我刚刚开始使用 Nunit 3.7.1、Newtonsoft.Json 版本=10.0.3、JustMock Lite 版本 2016.2.426.1、C# 和 .NET 进行一些测试框架 4.7.
我想测试这个class:
public class LoadFinishedTrzlBatch
{
private IGenericRepository<ProductionOrder> proOrdRepository;
private IGenericRepository<Batch> batchRepository;
private IGenericRepository<Code> codeRepository;
private IGenericRepository<Aggregation> aggregationRepository;
private IGenericRepository<AggregationChildren> aggChildrenRepository;
public LoadFinishedTrzlBatch(
IGenericRepository<ProductionOrder> proOrdRepository,
IGenericRepository<Batch> batchRepository,
IGenericRepository<Code> codeRepository,
IGenericRepository<Aggregation> aggregationRepository,
IGenericRepository<AggregationChildren> aggChildrenRepository)
{
this.proOrdRepository = proOrdRepository;
this.batchRepository = batchRepository;
this.codeRepository = codeRepository;
this.aggregationRepository = aggregationRepository;
this.aggChildrenRepository = aggChildrenRepository;
}
public bool ExistsProductionOrder(string productionOrderName)
{
if (string.IsNullOrWhiteSpace(productionOrderName))
throw new ArgumentNullException(nameof(productionOrderName));
return (
proOrdRepository
.SearchFor(p => p.Name == productionOrderName)
.FirstOrDefault() != null
);
}
}
通过此测试:
[TestFixture]
class LoadFinishedTrzlBatchTest
{
private LoadFinishedTrzlBatch _load;
[SetUp]
public void SetUpLoadFinishedTrzlBatch()
{
var proOrdRepository =
Mock.Create<IGenericRepository<ProductionOrder>>();
var batchRepository =
Mock.Create<IGenericRepository<Batch>>();
var codeRepository =
Mock.Create<IGenericRepository<Code>>();
var aggRepository =
Mock.Create<IGenericRepository<Aggregation>>();
var aggChildrenRepository =
Mock.Create<IGenericRepository<AggregationChildren>>();
_load = new LoadFinishedTrzlBatch(
proOrdRepository,
batchRepository,
codeRepository,
aggRepository,
aggChildrenRepository);
}
[Test]
public void ShouldExistsProductionOrder()
{
// Arrange
Mock.Arrange(() => _load.ExistsProductionOrder("ProOrd"))
.Returns(true)
.MustBeCalled();
// Act
var actual = _load.ExistsProductionOrder("ProOrd");
// Assert
Assert.AreEqual(actual, true);
}
}
最后是 IGenericRepository
:
public interface IGenericRepository<TEntity>
{
[ OMITTED ]
IQueryable<TEntity> SearchFor(Expression<Func<TEntity, bool>> predicate);
[ OMITTED ]
}
首先,我不确定这是否是测试方法 LoadFinishedTrzlBatch.ExistsProductionOrder
的正确方法。 TDD 对我来说一切都是新的,我迷路了。
我对我如何嘲笑 IGenericRepository<ProductionOrder>
感到困惑。它总是正确的,我没有测试 IGenericRepository<ProductionOrder>
。可能是因为我没有测试存储库。
我正在学习,但我不知道我在做什么。这就是我问这个问题的原因。我想测试 ExistsProductionOrder
方法。
如何测试 ExistsProductionOrder
方法?
实际上你想 测试 方法 ExistsProductionOrder
是否做了它应该做的事情。因此你不应该模拟它。但是,您想模拟在 方法中调用 的成员,例如对 IGenericRepository<T>.DoSomething()
.
的任何调用
然而只要调用它并将其结果与您期望的结果进行比较即可:
[Test]
public void ShouldExistsProductionOrder()
{
// Act
var actual = _load.ExistsProductionOrder("ProOrd");
Assert.IsTrue(actual);
}
现在,如果您的方法如下所示:
bool ExistsProductionOrder() {
this.proOrdRepository.DoSomething();
return ...
}
您可以将对 DoSomething
的调用替换为不同的东西 - 您的模拟。
你需要将目标依赖分离出来,这样才能在测试用例中隔离安排。您也不要模拟 SUT(被测对象)。你嘲笑它的依赖关系。在这种情况下,您想要模拟通用存储库并安排被调用的方法。即SearchFor
假设该方法采用表达式谓词,您可以将模拟安排为期望一个,然后将其应用于假集合存储以模拟实际数据存储。
[TestFixture]
public class LoadFinishedTrzlBatchTest {
private LoadFinishedTrzlBatch sut;
//need this later so declaring as field.
private IGenericRepository<ProductionOrder> proOrdRepository;
[SetUp]
public void SetUpLoadFinishedTrzlBatch() {
//Not using these so they can be declared locally
var batchRepository =
Mock.Create<IGenericRepository<Batch>>();
var codeRepository =
Mock.Create<IGenericRepository<Code>>();
var aggRepository =
Mock.Create<IGenericRepository<Aggregation>>();
var aggChildrenRepository =
Mock.Create<IGenericRepository<AggregationChildren>>();
//initializing target mock
proOrdRepository =
Mock.Create<IGenericRepository<ProductionOrder>>();
sut = new LoadFinishedTrzlBatch(
proOrdRepository,
batchRepository,
codeRepository,
aggRepository,
aggChildrenRepository);
}
[Test]
public void ShouldExistsProductionOrder()
{
// Arrange
var productionOrderName = "ProOrd";
var orders = new List<ProductionOrder>() {
new ProductionOrder { Name = productionOrderName },
new ProductionOrder { Name = "Dummy for Filter" }
};
Mock.Arrange(() => proOrdRepository
.SearchFor(Arg.IsAny<Expression<Func<ProductionOrder,bool>>>()))
.Returns((Expression<Func<ProductionOrder,bool>> expression) =>
orders.Where(expression.Compile()).AsQueryable()
)
.MustBeCalled();
// Act
var actual = sut.ExistsProductionOrder(productionOrderName);
// Assert
Assert.IsTrue(actual);
}
}
我是 TDD 开发的新手,我刚刚开始使用 Nunit 3.7.1、Newtonsoft.Json 版本=10.0.3、JustMock Lite 版本 2016.2.426.1、C# 和 .NET 进行一些测试框架 4.7.
我想测试这个class:
public class LoadFinishedTrzlBatch
{
private IGenericRepository<ProductionOrder> proOrdRepository;
private IGenericRepository<Batch> batchRepository;
private IGenericRepository<Code> codeRepository;
private IGenericRepository<Aggregation> aggregationRepository;
private IGenericRepository<AggregationChildren> aggChildrenRepository;
public LoadFinishedTrzlBatch(
IGenericRepository<ProductionOrder> proOrdRepository,
IGenericRepository<Batch> batchRepository,
IGenericRepository<Code> codeRepository,
IGenericRepository<Aggregation> aggregationRepository,
IGenericRepository<AggregationChildren> aggChildrenRepository)
{
this.proOrdRepository = proOrdRepository;
this.batchRepository = batchRepository;
this.codeRepository = codeRepository;
this.aggregationRepository = aggregationRepository;
this.aggChildrenRepository = aggChildrenRepository;
}
public bool ExistsProductionOrder(string productionOrderName)
{
if (string.IsNullOrWhiteSpace(productionOrderName))
throw new ArgumentNullException(nameof(productionOrderName));
return (
proOrdRepository
.SearchFor(p => p.Name == productionOrderName)
.FirstOrDefault() != null
);
}
}
通过此测试:
[TestFixture]
class LoadFinishedTrzlBatchTest
{
private LoadFinishedTrzlBatch _load;
[SetUp]
public void SetUpLoadFinishedTrzlBatch()
{
var proOrdRepository =
Mock.Create<IGenericRepository<ProductionOrder>>();
var batchRepository =
Mock.Create<IGenericRepository<Batch>>();
var codeRepository =
Mock.Create<IGenericRepository<Code>>();
var aggRepository =
Mock.Create<IGenericRepository<Aggregation>>();
var aggChildrenRepository =
Mock.Create<IGenericRepository<AggregationChildren>>();
_load = new LoadFinishedTrzlBatch(
proOrdRepository,
batchRepository,
codeRepository,
aggRepository,
aggChildrenRepository);
}
[Test]
public void ShouldExistsProductionOrder()
{
// Arrange
Mock.Arrange(() => _load.ExistsProductionOrder("ProOrd"))
.Returns(true)
.MustBeCalled();
// Act
var actual = _load.ExistsProductionOrder("ProOrd");
// Assert
Assert.AreEqual(actual, true);
}
}
最后是 IGenericRepository
:
public interface IGenericRepository<TEntity>
{
[ OMITTED ]
IQueryable<TEntity> SearchFor(Expression<Func<TEntity, bool>> predicate);
[ OMITTED ]
}
首先,我不确定这是否是测试方法 LoadFinishedTrzlBatch.ExistsProductionOrder
的正确方法。 TDD 对我来说一切都是新的,我迷路了。
我对我如何嘲笑 IGenericRepository<ProductionOrder>
感到困惑。它总是正确的,我没有测试 IGenericRepository<ProductionOrder>
。可能是因为我没有测试存储库。
我正在学习,但我不知道我在做什么。这就是我问这个问题的原因。我想测试 ExistsProductionOrder
方法。
如何测试 ExistsProductionOrder
方法?
实际上你想 测试 方法 ExistsProductionOrder
是否做了它应该做的事情。因此你不应该模拟它。但是,您想模拟在 方法中调用 的成员,例如对 IGenericRepository<T>.DoSomething()
.
然而只要调用它并将其结果与您期望的结果进行比较即可:
[Test]
public void ShouldExistsProductionOrder()
{
// Act
var actual = _load.ExistsProductionOrder("ProOrd");
Assert.IsTrue(actual);
}
现在,如果您的方法如下所示:
bool ExistsProductionOrder() {
this.proOrdRepository.DoSomething();
return ...
}
您可以将对 DoSomething
的调用替换为不同的东西 - 您的模拟。
你需要将目标依赖分离出来,这样才能在测试用例中隔离安排。您也不要模拟 SUT(被测对象)。你嘲笑它的依赖关系。在这种情况下,您想要模拟通用存储库并安排被调用的方法。即SearchFor
假设该方法采用表达式谓词,您可以将模拟安排为期望一个,然后将其应用于假集合存储以模拟实际数据存储。
[TestFixture]
public class LoadFinishedTrzlBatchTest {
private LoadFinishedTrzlBatch sut;
//need this later so declaring as field.
private IGenericRepository<ProductionOrder> proOrdRepository;
[SetUp]
public void SetUpLoadFinishedTrzlBatch() {
//Not using these so they can be declared locally
var batchRepository =
Mock.Create<IGenericRepository<Batch>>();
var codeRepository =
Mock.Create<IGenericRepository<Code>>();
var aggRepository =
Mock.Create<IGenericRepository<Aggregation>>();
var aggChildrenRepository =
Mock.Create<IGenericRepository<AggregationChildren>>();
//initializing target mock
proOrdRepository =
Mock.Create<IGenericRepository<ProductionOrder>>();
sut = new LoadFinishedTrzlBatch(
proOrdRepository,
batchRepository,
codeRepository,
aggRepository,
aggChildrenRepository);
}
[Test]
public void ShouldExistsProductionOrder()
{
// Arrange
var productionOrderName = "ProOrd";
var orders = new List<ProductionOrder>() {
new ProductionOrder { Name = productionOrderName },
new ProductionOrder { Name = "Dummy for Filter" }
};
Mock.Arrange(() => proOrdRepository
.SearchFor(Arg.IsAny<Expression<Func<ProductionOrder,bool>>>()))
.Returns((Expression<Func<ProductionOrder,bool>> expression) =>
orders.Where(expression.Compile()).AsQueryable()
)
.MustBeCalled();
// Act
var actual = sut.ExistsProductionOrder(productionOrderName);
// Assert
Assert.IsTrue(actual);
}
}