单元测试中的模拟在LINQ.Where返回null

时间:2018-04-03 07:41:23

标签: c# linq unit-testing mocking moq

我想要将两个类BeamTreatment与其值DateTime TimeStamp匹配。因此,在我的代码中,我有一个LINQ .Where()来搜索特殊的TimeStamp并将其与预先排序的列表进行比较。使用真实数据它可以很好地运行并且没有任何错误,但是现在我被告知要为这个类写一个单元测试并且使用Moq我没有得到预期的结果。

我的代码中的行不起作用是:

Treatment searchedBeam = (Treatment)InputData.Treatments.
    Where(beam => beam.TimeStamp == sortingList[j + i * rangeOfBeams]).FirstOrDefault();

i,j是来自for循环的索引,并且正如我在调试模式中看到的那样正确运行。

在我的单元测试代码中,我有这个:

Mock<ITreatmentGroup> treatGroupMock1;
[SetUp]
public override void Init()
{
    base.Init();

    // --- Create Plan Mock
    // some code here

    // --- Create Treatment Mock
    DateTime time1 = new DateTime(2000, 01, 01, 12, 00, 00);
    DateTime time2 = new DateTime(2000, 01, 01, 13, 00, 00);

    Mock<ITreatment> treatMock1 = new Mock<ITreatment>();
    treatMock1.Setup(t => t.TimeStamp).Returns(time1);
    Mock<ITreatment> treatMock2 = new Mock<ITreatment>();
    treatMock2.Setup(t => t.TimeStamp).Returns(time2);

    treatGroupMock1 = new Mock<ITreatmentGroup>();
    treatGroupMock1.Setup(tg => tg.Treatments).Returns(new List<ITreatment>() { treatMock1.Object, treatMock2.Object });
}

在调试中,我检查了模拟数据与真实数据的结构相同。但接下来是我的测试代码:

[Test]
public void Matched_MatchedAndSortedPlan_FunctionCheck()
{
    IPlan result = Matched.MatchedAndSortedPlan(_planMock.Object, _treatGroupMock1.Object, out IList<string> errors);

    Assert.IsEmpty(errors);
    Assert.IsNotNull(result);
    Assert.IsTrue(result.FractionGroups[0].Beams.Any(f => f.BeamName == "beamMock1"));              
}

所以我用模拟数据调用我的方法,并且与实际数据一样,它应该可以工作,但正如我所提到的,LINQ表达式的行返回null所以Assert命令让单元测试失败。

我得到的最大提示是模拟LINQ表达式存在一些问题,但我不想模拟LINQ表达式,而是将其用于我的解决方案。其他问题,如thisthis,Google将我作为搜索的首次点击,我认为这里不起作用。

我希望你能为我提供另一条线索或暗示。

1 个答案:

答案 0 :(得分:2)

Linq Where工作正常。由于尝试从模拟接口转换为具体类型,searchedBeam被分配null

                          right here
                              |
                              v
Treatment searchedBeam = (Treatment)InputData.Treatments.
    Where(beam => beam.TimeStamp == sortingList[j + i * rangeOfBeams]).FirstOrDefault();

您将返回的结果投射到Treatment,而在测试集合中设置的项目只是ITreatment的模拟。

如果您能够创建Treatment的实际实例而没有副作用,那么创建并使用它们进行测试

[SetUp]
public override void Init() {
    base.Init();

    // --- Create Plan Mock
    // some code here

    // --- Create Treatment Mock
    DateTime time1 = new DateTime(2000, 01, 01, 12, 00, 00);
    DateTime time2 = new DateTime(2000, 01, 01, 13, 00, 00);

    var treatMock1 = new Treatment {
        TimeStamp = time1
    };
    var treatMock2 = new Treatment {
        TimeStamp = time2
    };

    treatGroupMock1 = new Mock<ITreatmentGroup>();
    treatGroupMock1.Setup(_ => _.Treatments).Returns(new List<ITreatment>() { treatMock1, treatMock2 });
}

这样,演员在进行测试时表现得像预期的那样。

相关问题