普通类的Mock

加上Virtual

有时候我们的系统当中很多是旧代码,或者其它的原因,我们的类依赖的不是接口(抽象类)而是具体类。 这个时候我们希望对它进行Mock的话,我们就需要把它的方法加上virtual

public class SettingService
{
    public virtual StudentSetting GetStudentSetting(string name)
    {
        return new StudentSetting() { };
    }
}

public class StudentSetting
{
    public int MaxAge { get; set; }
    public string Name { get; set; }
}
[Fact]
public void Test_Class()
{
    var studentSetting = new StudentSetting()
    {
        MaxAge = 1
    };
    var settingService = new Mock<SettingService>();

    settingService.Setup(x => x.GetStudentSetting("aa")).Returns(studentSetting);
    settingService.Object.GetStudentSetting("aa").Should().Be(studentSetting);
    settingService.Verify(x => x.GetStudentSetting("aa"), Times.Once);
}

有参构造函数

public class SettingService
{
    public readonly int Age;
    public SettingService(int age)
    {
        this.Age = age;
    }
}

[Fact]
public void Test_Class()
{
    // 有几个参数,这边就要加上几个参数。我们的例子是一个参数,所以这边只需要一个
    var settingService = new Mock<SettingService>(10); 
}

Callbase

public class SettingService
{
    public string A1()
    {
        return "a1" + A2() + A3();
    }

//注意 有 virtual 
    public virtual string A2()
    {
        return "a2";
    }
//注意 没有 virtual 
    public string A3()
    {
        return "a3";
    }
}

[Fact]
public void Test_Class()
{
    var settingService = new Mock<SettingService>();
    // a2 方法默认被moq重写掉了。所以返回了a1a3
    settingService.Object.A1().Should().Be("a1a3");

    var settingService2 = new Mock<SettingService>()
    {
        CallBase = true
    };

    //使用callbase,没有重写的调用原生的方法
    settingService2.Object.A1().Should().Be("a1a2a3");

    
    var settingService3 = new Mock<SettingService>()
    {
        CallBase = true
    };
    //mock了a2方法, callbase对此无效了
    settingService3.Setup(x => x.A2()).Returns("b2");
    settingService3.Object.A1().Should().Be("a1b2a3");
}

Mock protected 方法

因为 protected方法也是可以被子类重写的。所以我们也是可以对它进行Mock.

public class SettingService
{
    public string AA(string name)
    {
        return "AA:" + A1(name);
    }

    protected virtual string A1(string name)
    {
        return "A1:" + name;
    }
}
using FluentAssertions;
using Moq;
using Moq.Protected;
using Xunit;
namespace MyFirstUnitTests
{
    public class StudentServiceTest
    {
        [Fact]
        public void Test_Protected()
        {
            var settingService = new Mock<SettingService>();
            //需要引用Moq.Protected;
            settingService.Protected().Setup<string>("A1", ItExpr.IsAny<string>()).Returns("qqq");

            settingService.Object.AA("sss").Should().Be("AA:qqq");
        }
    }
}

internal 方法

有时有一些方法是用internal来修饰的。 这个时候我们可以用InternalsVisibleToAttribute。 最好是加在项目AssemblyInfo.cs哪边。这样整个项目都是有效果

[assembly: InternalsVisibleToAttribute("projectName")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]  //这个是Moq的namespace
上一篇:Moq的介绍
下一篇:Mock 静态方法
最近更新的
...