【问题标题】:Unit Test for two classes inherit an Interface两个类的单元测试继承一个接口
【发布时间】:2015-04-21 21:15:46
【问题描述】:

我有两个实现接口的类,但是这两个类都有一个参数传递给构造函数来确定应用程序需要什么类。当我创建 AvailablityRepoData 的实例时,我正在尝试在 (AvailablityRepoData) 类上测试一个 (GetAvailablity) 方法我收到非虚拟方法的错误。如果有人能指出正确的方向,我将不胜感激。

public interface IAvailablityRepo
   {
     string  GetAvailablity(Availablity availablity);
}
public class AvailablityRepoData: IAvailablityRepo
{

    public AvailablityRepoData(string websetting) {
    }
    public string GetAvailablity(Availablity availablity) {
        return "Data";
    }
}

public class AvailablityRepoWeb:IAvailablityRepo
{
    public AvailablityRepoWeb(string DataSetting) {
    }
    public string GetAvailablity(Availablity availablity) {
        return "Web";
    }
}

public class Availablity
{
    public virtual string Id {
        get;
        set;
    }
    public virtual string  Status {
        get;
        set;
    }
}

        var a = new Availablity() { Id = "111", Status = "A"};
        Mock<IAvailablityRepo> mockRepo = new Mock<IAvailablityRepo>();
        Mock<IAvailablityRepo> RepoData = new Mock<IAvailablityRepo>();
        RepoData.Setup(x => x.GetAvailablity(It.IsAny<Availablity>  ())).Returns("pass");
        var result = RepoData.Object.GetAvailablity(a);

【问题讨论】:

  • 请正确格式化您的代码。
  • 确切的错误是什么?另外,是运行时错误还是编译时错误?
  • 运行时错误我不想在 AvailablityRepoData 上创建 Get GetAvailablity 虚拟方法
  • 您可以添加整个错误消息吗?从您的代码 sn-p 不能立即清楚出了什么问题。
  • 作为旁注:测试目前只是测试起订量是否按预期工作。您正在提供 GetAvailablility 的假实现,并直接检查此假实现是否返回正确的响应。此测试不是测试单行生产代码。

标签: c# asp.net-mvc unit-testing tdd moq


【解决方案1】:

正如 cmets 中已经说过的,从您发布的代码中并不清楚您的错误是什么。如果我将其直接复制并粘贴到 Visual Studio 中(将测试代码包装在测试中),则测试通过。我将建议,当您遇到错误时,您的测试代码实际上更接近于这个:

[TestMethod]
public void TestMethod1() {
    var a = new Availablity() { Id = "111", Status = "A" };
    Mock<IAvailablityRepo> mockRepo = new Mock<IAvailablityRepo>();
    Mock<AvailablityRepoData> RepoData = new Mock<AvailablityRepoData>();
    RepoData.Setup(x => x.GetAvailablity(It.IsAny<Availablity>())).Returns("pass");
    var result = RepoData.Object.GetAvailablity(a);
}

这会导致测试运行时出错:

System.NotSupportedException:Invalid setup on a non-virtual (overridable in VB) member:
                             x => x.GetAvailablity(It.IsAny<Availablity>())

这个测试和你原来的测试的不同之处在于,我将 Mocked 类型从接口 IAvailabilityRepo 更改为 AvailabilityRepoData,这是具体的类。由于 Moq 只支持模拟接口/虚拟方法,它自然会感到不安。

正如@prgmtc 所提到的,您的测试目前并没有真正测试任何东西。

使用您当前的代码,看起来您根本不需要使用 Mocks。像这样的东西可能是更合适的测试:

[TestMethod]
public void TestDataRepoReturnsDataAvailability() {
    var someImportantSetting = "thisShouldBeSomethingMeaningful";
    var availability = new Availablity() { Id = "111", Status = "A" };
    var sut = new AvailablityRepoData(someImportantSetting);

    var returnedAvailability = sut.GetAvailablity(availability);

    Assert.AreEqual("Data", returnedAvailability);
}

假设您的实际代码更复杂,传递到数据仓库的字符串可能需要更有意义...

作为一般经验法则,您不应该嘲笑被测系统。如果您发现自己为您正在测试的系统创建了一个模拟,这很好地表明您在一个类中有很多功能和/或您正在尝试测试错误的东西......

顺便说一句,您可能希望查看 builder pattern 之类的东西来创建不同的存储库,而不是像您建议的那样将类型传递给每个存储库的构造函数。

【讨论】:

    猜你喜欢
    • 2018-03-14
    • 2021-09-12
    • 1970-01-01
    • 2019-08-04
    • 2016-03-30
    • 1970-01-01
    • 2013-12-11
    • 1970-01-01
    • 2014-03-09
    相关资源
    最近更新 更多