模拟IList的单元测试方法

时间:2017-02-28 15:05:07

标签: c# unit-testing autofixture

我试图模仿以下方法 TryGetApns

    private readonly Func<string, ICommunicationClient> _communicationFactory;

    public CommunicationApiFacade(Func<string, ICommunicationClient> communicationFactory)
    {
        _communicationFactory = communicationFactory;
    }

    public IList<ApnResponse> TryGetApns(string tenant)
    {
        GetApnsResponse response = null;
        try
        {
            var communicationApiClient = _communicationFactory(tenant);
            response = communicationApiClient.JctConfigurationService.GetApns();
        }
        catch (HttpException e)
        {
            ...
        }

        return response?.Apns ?? new List<ApnResponse>();
    }

进行以下测试:

    private Mock<ICommunicationApiFacade> _communicationApiFacade;

    [SetUp]
    public void SetUp()
    {
        _fixture = new Fixture()
            .Customize(new AutoMoqCustomization());

        _communicationApiFacade = _fixture.Freeze<Mock<ICommunicationApiFacade>>();
    }

    [Test]
    public void RunJctTests_WhenJctIsInAPrivateNetwork_ShouldReturnAPassedTest()
    {
        // Arrange
        var jctApn = _fixture.Create<string>();
        var message = _fixture.Build<JctLoggedIn>()
            .With(x => x.ApnFromDevice, jctApn)
            .Create();

        var response = _fixture.Build<ApnResponse>()
            .With(x => x.IsPrivateApn, true)
            .With(x => x.ApnName, jctApn).Create();

        _communicationApiFacade.Setup(x => x.TryGetApns(string.Empty))
            .Returns(new List<ApnResponse> { response });

        var subject = _fixture.Create<NetworkProviderTestRunner>();

        // Act
        var result = subject.Execute(message);

        // Assert
        Assert.That(result.Result, Is.True);
    }

这是 NetworkProviderTestRunner 类:

    private readonly ICommunicationApiFacade _communicationApi;

    public NetworkProviderTestRunner(ICommunicationApiFacade communicationApi)
    {
        _communicationApi = communicationApi;
    }

    public JctTest Execute(JctLoggedIn message)
    {
        var apns = _communicationApi.TryGetApns(message.Tenant);

        var jctApn = apns.FirstOrDefault(x => x.ApnName == message.ApnFromDevice);

        if (jctApn != null)
        {
            var privateApn = apns.FirstOrDefault(x => x.PublicApnId.Equals(jctApn.Id));
            if (privateApn != null || jctApn.IsPrivateApn)
                return new JctTest { Result = true };
        }
        return new JctTest { Result = false };
    }

JctLoggedIn 类:

public class JctLoggedIn : Message
{
    public string Imei { get; set; }
    public string SimCardIdFromDevice { get; set; }
    public string SimCardIdFromStorage { get; set; }
    public string ApnFromDevice { get; set; }
    public string ApnFromStorage { get; set; }
    public string FirmwareFromDevice { get; set; }
    public int DeviceTypeFromStorage { get; set; }
    public int SerialNumber { get; set; }
}

但由于某种原因,我总是得到一个空列表。我试图在SetUp中填充列表并在那里定义输出,但我总是一样。有什么帮助吗?

3 个答案:

答案 0 :(得分:3)

虽然在构建Tenant对象时可以明确省略message属性,但您也可以将Mock设置更改为:

_communicationApiFacade.Setup(x => x.TryGetApns(message.Tenant))
    .Returns(new List<ApnResponse> { response });

答案 1 :(得分:0)

这一行

_communicationApiFacade.Setup(x => x.TryGetApns(string.Empty))
        .Returns(new List<ApnResponse> { response });

告诉mock在调用TryGetApns时返回包含响应的列表,并为租户参数添加一个空字符串。

此行创建消息后,message.Tenant的值是什么:

var message = _fixture.Build<JctLoggedIn>()
        .With(x => x.ApnFromDevice, jctApn)
        .Create();

如果它不是string.empty,那么你的模拟将不会返回响应列表。

答案 2 :(得分:0)

替换

var response = _fixture.Build<ApnResponse>()
            .With(x => x.IsPrivateApn, true)
            .With(x => x.ApnName, jctApn).Create();

var response = _fixture.Build<ApnResponse>()
            .With(x => x.Tenant, String.Empty)
            .With(x => x.IsPrivateApn, true)
            .With(x => x.ApnName, jctApn).Create();

如果租客是可写的。

如果属性是可写的,AutoFixture将为租户创建一个非空值的对象,而无需明确设置您想要的内容。